diff options
| author | orivej <[email protected]> | 2022-02-10 16:44:49 +0300 |
|---|---|---|
| committer | Daniil Cherednik <[email protected]> | 2022-02-10 16:44:49 +0300 |
| commit | 718c552901d703c502ccbefdfc3c9028d608b947 (patch) | |
| tree | 46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/libs/llvm12/include/llvm/Object/ELFObjectFile.h | |
| parent | e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff) | |
Restoring authorship annotation for <[email protected]>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/llvm12/include/llvm/Object/ELFObjectFile.h')
| -rw-r--r-- | contrib/libs/llvm12/include/llvm/Object/ELFObjectFile.h | 2280 |
1 files changed, 1140 insertions, 1140 deletions
diff --git a/contrib/libs/llvm12/include/llvm/Object/ELFObjectFile.h b/contrib/libs/llvm12/include/llvm/Object/ELFObjectFile.h index 28c6ec9bfc8..40bd4150202 100644 --- a/contrib/libs/llvm12/include/llvm/Object/ELFObjectFile.h +++ b/contrib/libs/llvm12/include/llvm/Object/ELFObjectFile.h @@ -1,415 +1,415 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- ELFObjectFile.h - ELF object file implementation ---------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the ELFObjectFile template class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_ELFOBJECTFILE_H -#define LLVM_OBJECT_ELFOBJECTFILE_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/MC/SubtargetFeature.h" -#include "llvm/Object/Binary.h" -#include "llvm/Object/ELF.h" -#include "llvm/Object/ELFTypes.h" -#include "llvm/Object/Error.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Object/SymbolicFile.h" -#include "llvm/Support/ARMAttributeParser.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ELFAttributes.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MemoryBuffer.h" -#include <cassert> -#include <cstdint> -#include <system_error> - -namespace llvm { -namespace object { - -constexpr int NumElfSymbolTypes = 16; -extern const llvm::EnumEntry<unsigned> ElfSymbolTypes[NumElfSymbolTypes]; - -class elf_symbol_iterator; - -class ELFObjectFileBase : public ObjectFile { - friend class ELFRelocationRef; - friend class ELFSectionRef; - friend class ELFSymbolRef; - +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- ELFObjectFile.h - ELF object file implementation ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the ELFObjectFile template class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_ELFOBJECTFILE_H +#define LLVM_OBJECT_ELFOBJECTFILE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/ELF.h" +#include "llvm/Object/ELFTypes.h" +#include "llvm/Object/Error.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/SymbolicFile.h" +#include "llvm/Support/ARMAttributeParser.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ELFAttributes.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include <cassert> +#include <cstdint> +#include <system_error> + +namespace llvm { +namespace object { + +constexpr int NumElfSymbolTypes = 16; +extern const llvm::EnumEntry<unsigned> ElfSymbolTypes[NumElfSymbolTypes]; + +class elf_symbol_iterator; + +class ELFObjectFileBase : public ObjectFile { + friend class ELFRelocationRef; + friend class ELFSectionRef; + friend class ELFSymbolRef; + SubtargetFeatures getMIPSFeatures() const; SubtargetFeatures getARMFeatures() const; SubtargetFeatures getRISCVFeatures() const; StringRef getAMDGPUCPUName() const; -protected: - ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source); - - virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0; - virtual uint8_t getSymbolBinding(DataRefImpl Symb) const = 0; - virtual uint8_t getSymbolOther(DataRefImpl Symb) const = 0; - virtual uint8_t getSymbolELFType(DataRefImpl Symb) const = 0; - - virtual uint32_t getSectionType(DataRefImpl Sec) const = 0; - virtual uint64_t getSectionFlags(DataRefImpl Sec) const = 0; - virtual uint64_t getSectionOffset(DataRefImpl Sec) const = 0; - - virtual Expected<int64_t> getRelocationAddend(DataRefImpl Rel) const = 0; - virtual Error getBuildAttributes(ELFAttributeParser &Attributes) const = 0; - -public: - using elf_symbol_iterator_range = iterator_range<elf_symbol_iterator>; - - virtual elf_symbol_iterator_range getDynamicSymbolIterators() const = 0; - - /// Returns platform-specific object flags, if any. - virtual unsigned getPlatformFlags() const = 0; - - elf_symbol_iterator_range symbols() const; - - static bool classof(const Binary *v) { return v->isELF(); } - - SubtargetFeatures getFeatures() const override; - +protected: + ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source); + + virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0; + virtual uint8_t getSymbolBinding(DataRefImpl Symb) const = 0; + virtual uint8_t getSymbolOther(DataRefImpl Symb) const = 0; + virtual uint8_t getSymbolELFType(DataRefImpl Symb) const = 0; + + virtual uint32_t getSectionType(DataRefImpl Sec) const = 0; + virtual uint64_t getSectionFlags(DataRefImpl Sec) const = 0; + virtual uint64_t getSectionOffset(DataRefImpl Sec) const = 0; + + virtual Expected<int64_t> getRelocationAddend(DataRefImpl Rel) const = 0; + virtual Error getBuildAttributes(ELFAttributeParser &Attributes) const = 0; + +public: + using elf_symbol_iterator_range = iterator_range<elf_symbol_iterator>; + + virtual elf_symbol_iterator_range getDynamicSymbolIterators() const = 0; + + /// Returns platform-specific object flags, if any. + virtual unsigned getPlatformFlags() const = 0; + + elf_symbol_iterator_range symbols() const; + + static bool classof(const Binary *v) { return v->isELF(); } + + SubtargetFeatures getFeatures() const override; + Optional<StringRef> tryGetCPUName() const override; - - void setARMSubArch(Triple &TheTriple) const override; - - virtual uint16_t getEType() const = 0; - - virtual uint16_t getEMachine() const = 0; - + + void setARMSubArch(Triple &TheTriple) const override; + + virtual uint16_t getEType() const = 0; + + virtual uint16_t getEMachine() const = 0; + std::vector<std::pair<Optional<DataRefImpl>, uint64_t>> getPltAddresses() const; -}; - -class ELFSectionRef : public SectionRef { -public: - ELFSectionRef(const SectionRef &B) : SectionRef(B) { - assert(isa<ELFObjectFileBase>(SectionRef::getObject())); - } - - const ELFObjectFileBase *getObject() const { - return cast<ELFObjectFileBase>(SectionRef::getObject()); - } - - uint32_t getType() const { - return getObject()->getSectionType(getRawDataRefImpl()); - } - - uint64_t getFlags() const { - return getObject()->getSectionFlags(getRawDataRefImpl()); - } - - uint64_t getOffset() const { - return getObject()->getSectionOffset(getRawDataRefImpl()); - } -}; - -class elf_section_iterator : public section_iterator { -public: - elf_section_iterator(const section_iterator &B) : section_iterator(B) { - assert(isa<ELFObjectFileBase>(B->getObject())); - } - - const ELFSectionRef *operator->() const { - return static_cast<const ELFSectionRef *>(section_iterator::operator->()); - } - - const ELFSectionRef &operator*() const { - return static_cast<const ELFSectionRef &>(section_iterator::operator*()); - } -}; - -class ELFSymbolRef : public SymbolRef { -public: - ELFSymbolRef(const SymbolRef &B) : SymbolRef(B) { - assert(isa<ELFObjectFileBase>(SymbolRef::getObject())); - } - - const ELFObjectFileBase *getObject() const { - return cast<ELFObjectFileBase>(BasicSymbolRef::getObject()); - } - - uint64_t getSize() const { - return getObject()->getSymbolSize(getRawDataRefImpl()); - } - - uint8_t getBinding() const { - return getObject()->getSymbolBinding(getRawDataRefImpl()); - } - - uint8_t getOther() const { - return getObject()->getSymbolOther(getRawDataRefImpl()); - } - - uint8_t getELFType() const { - return getObject()->getSymbolELFType(getRawDataRefImpl()); - } - - StringRef getELFTypeName() const { - uint8_t Type = getELFType(); - for (auto &EE : ElfSymbolTypes) { - if (EE.Value == Type) { - return EE.AltName; - } - } - return ""; - } -}; - -class elf_symbol_iterator : public symbol_iterator { -public: - elf_symbol_iterator(const basic_symbol_iterator &B) - : symbol_iterator(SymbolRef(B->getRawDataRefImpl(), - cast<ELFObjectFileBase>(B->getObject()))) {} - - const ELFSymbolRef *operator->() const { - return static_cast<const ELFSymbolRef *>(symbol_iterator::operator->()); - } - - const ELFSymbolRef &operator*() const { - return static_cast<const ELFSymbolRef &>(symbol_iterator::operator*()); - } -}; - -class ELFRelocationRef : public RelocationRef { -public: - ELFRelocationRef(const RelocationRef &B) : RelocationRef(B) { - assert(isa<ELFObjectFileBase>(RelocationRef::getObject())); - } - - const ELFObjectFileBase *getObject() const { - return cast<ELFObjectFileBase>(RelocationRef::getObject()); - } - - Expected<int64_t> getAddend() const { - return getObject()->getRelocationAddend(getRawDataRefImpl()); - } -}; - -class elf_relocation_iterator : public relocation_iterator { -public: - elf_relocation_iterator(const relocation_iterator &B) - : relocation_iterator(RelocationRef( - B->getRawDataRefImpl(), cast<ELFObjectFileBase>(B->getObject()))) {} - - const ELFRelocationRef *operator->() const { - return static_cast<const ELFRelocationRef *>( - relocation_iterator::operator->()); - } - - const ELFRelocationRef &operator*() const { - return static_cast<const ELFRelocationRef &>( - relocation_iterator::operator*()); - } -}; - -inline ELFObjectFileBase::elf_symbol_iterator_range -ELFObjectFileBase::symbols() const { - return elf_symbol_iterator_range(symbol_begin(), symbol_end()); -} - -template <class ELFT> class ELFObjectFile : public ELFObjectFileBase { - uint16_t getEMachine() const override; - uint16_t getEType() const override; - uint64_t getSymbolSize(DataRefImpl Sym) const override; - -public: - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - - SectionRef toSectionRef(const Elf_Shdr *Sec) const { - return SectionRef(toDRI(Sec), this); - } - +}; + +class ELFSectionRef : public SectionRef { +public: + ELFSectionRef(const SectionRef &B) : SectionRef(B) { + assert(isa<ELFObjectFileBase>(SectionRef::getObject())); + } + + const ELFObjectFileBase *getObject() const { + return cast<ELFObjectFileBase>(SectionRef::getObject()); + } + + uint32_t getType() const { + return getObject()->getSectionType(getRawDataRefImpl()); + } + + uint64_t getFlags() const { + return getObject()->getSectionFlags(getRawDataRefImpl()); + } + + uint64_t getOffset() const { + return getObject()->getSectionOffset(getRawDataRefImpl()); + } +}; + +class elf_section_iterator : public section_iterator { +public: + elf_section_iterator(const section_iterator &B) : section_iterator(B) { + assert(isa<ELFObjectFileBase>(B->getObject())); + } + + const ELFSectionRef *operator->() const { + return static_cast<const ELFSectionRef *>(section_iterator::operator->()); + } + + const ELFSectionRef &operator*() const { + return static_cast<const ELFSectionRef &>(section_iterator::operator*()); + } +}; + +class ELFSymbolRef : public SymbolRef { +public: + ELFSymbolRef(const SymbolRef &B) : SymbolRef(B) { + assert(isa<ELFObjectFileBase>(SymbolRef::getObject())); + } + + const ELFObjectFileBase *getObject() const { + return cast<ELFObjectFileBase>(BasicSymbolRef::getObject()); + } + + uint64_t getSize() const { + return getObject()->getSymbolSize(getRawDataRefImpl()); + } + + uint8_t getBinding() const { + return getObject()->getSymbolBinding(getRawDataRefImpl()); + } + + uint8_t getOther() const { + return getObject()->getSymbolOther(getRawDataRefImpl()); + } + + uint8_t getELFType() const { + return getObject()->getSymbolELFType(getRawDataRefImpl()); + } + + StringRef getELFTypeName() const { + uint8_t Type = getELFType(); + for (auto &EE : ElfSymbolTypes) { + if (EE.Value == Type) { + return EE.AltName; + } + } + return ""; + } +}; + +class elf_symbol_iterator : public symbol_iterator { +public: + elf_symbol_iterator(const basic_symbol_iterator &B) + : symbol_iterator(SymbolRef(B->getRawDataRefImpl(), + cast<ELFObjectFileBase>(B->getObject()))) {} + + const ELFSymbolRef *operator->() const { + return static_cast<const ELFSymbolRef *>(symbol_iterator::operator->()); + } + + const ELFSymbolRef &operator*() const { + return static_cast<const ELFSymbolRef &>(symbol_iterator::operator*()); + } +}; + +class ELFRelocationRef : public RelocationRef { +public: + ELFRelocationRef(const RelocationRef &B) : RelocationRef(B) { + assert(isa<ELFObjectFileBase>(RelocationRef::getObject())); + } + + const ELFObjectFileBase *getObject() const { + return cast<ELFObjectFileBase>(RelocationRef::getObject()); + } + + Expected<int64_t> getAddend() const { + return getObject()->getRelocationAddend(getRawDataRefImpl()); + } +}; + +class elf_relocation_iterator : public relocation_iterator { +public: + elf_relocation_iterator(const relocation_iterator &B) + : relocation_iterator(RelocationRef( + B->getRawDataRefImpl(), cast<ELFObjectFileBase>(B->getObject()))) {} + + const ELFRelocationRef *operator->() const { + return static_cast<const ELFRelocationRef *>( + relocation_iterator::operator->()); + } + + const ELFRelocationRef &operator*() const { + return static_cast<const ELFRelocationRef &>( + relocation_iterator::operator*()); + } +}; + +inline ELFObjectFileBase::elf_symbol_iterator_range +ELFObjectFileBase::symbols() const { + return elf_symbol_iterator_range(symbol_begin(), symbol_end()); +} + +template <class ELFT> class ELFObjectFile : public ELFObjectFileBase { + uint16_t getEMachine() const override; + uint16_t getEType() const override; + uint64_t getSymbolSize(DataRefImpl Sym) const override; + +public: + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + + SectionRef toSectionRef(const Elf_Shdr *Sec) const { + return SectionRef(toDRI(Sec), this); + } + ELFSymbolRef toSymbolRef(const Elf_Shdr *SymTable, unsigned SymbolNum) const { return ELFSymbolRef({toDRI(SymTable, SymbolNum), this}); } bool IsContentValid() const { return ContentValid; } -private: - ELFObjectFile(MemoryBufferRef Object, ELFFile<ELFT> EF, - const Elf_Shdr *DotDynSymSec, const Elf_Shdr *DotSymtabSec, +private: + ELFObjectFile(MemoryBufferRef Object, ELFFile<ELFT> EF, + const Elf_Shdr *DotDynSymSec, const Elf_Shdr *DotSymtabSec, const Elf_Shdr *DotSymtabShndxSec); - + bool ContentValid = false; -protected: - ELFFile<ELFT> EF; - - const Elf_Shdr *DotDynSymSec = nullptr; // Dynamic symbol table section. - const Elf_Shdr *DotSymtabSec = nullptr; // Symbol table section. +protected: + ELFFile<ELFT> EF; + + const Elf_Shdr *DotDynSymSec = nullptr; // Dynamic symbol table section. + const Elf_Shdr *DotSymtabSec = nullptr; // Symbol table section. const Elf_Shdr *DotSymtabShndxSec = nullptr; // SHT_SYMTAB_SHNDX section. - + Error initContent() override; - void moveSymbolNext(DataRefImpl &Symb) const override; - Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; - Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; - uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; - uint32_t getSymbolAlignment(DataRefImpl Symb) const override; - uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; - Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override; - uint8_t getSymbolBinding(DataRefImpl Symb) const override; - uint8_t getSymbolOther(DataRefImpl Symb) const override; - uint8_t getSymbolELFType(DataRefImpl Symb) const override; - Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; - Expected<section_iterator> getSymbolSection(const Elf_Sym *Symb, - const Elf_Shdr *SymTab) const; - Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; - - void moveSectionNext(DataRefImpl &Sec) const override; - Expected<StringRef> getSectionName(DataRefImpl Sec) const override; - uint64_t getSectionAddress(DataRefImpl Sec) const override; - uint64_t getSectionIndex(DataRefImpl Sec) const override; - uint64_t getSectionSize(DataRefImpl Sec) const override; - Expected<ArrayRef<uint8_t>> - getSectionContents(DataRefImpl Sec) const override; - uint64_t getSectionAlignment(DataRefImpl Sec) const override; - bool isSectionCompressed(DataRefImpl Sec) const override; - bool isSectionText(DataRefImpl Sec) const override; - bool isSectionData(DataRefImpl Sec) const override; - bool isSectionBSS(DataRefImpl Sec) const override; - bool isSectionVirtual(DataRefImpl Sec) const override; - bool isBerkeleyText(DataRefImpl Sec) const override; - bool isBerkeleyData(DataRefImpl Sec) const override; - bool isDebugSection(StringRef SectionName) const override; - relocation_iterator section_rel_begin(DataRefImpl Sec) const override; - relocation_iterator section_rel_end(DataRefImpl Sec) const override; - std::vector<SectionRef> dynamic_relocation_sections() const override; - Expected<section_iterator> - getRelocatedSection(DataRefImpl Sec) const override; - - void moveRelocationNext(DataRefImpl &Rel) const override; - uint64_t getRelocationOffset(DataRefImpl Rel) const override; - symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; - uint64_t getRelocationType(DataRefImpl Rel) const override; - void getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const override; - - uint32_t getSectionType(DataRefImpl Sec) const override; - uint64_t getSectionFlags(DataRefImpl Sec) const override; - uint64_t getSectionOffset(DataRefImpl Sec) const override; - StringRef getRelocationTypeName(uint32_t Type) const; - - DataRefImpl toDRI(const Elf_Shdr *SymTable, unsigned SymbolNum) const { - DataRefImpl DRI; - if (!SymTable) { - DRI.d.a = 0; - DRI.d.b = 0; - return DRI; - } - assert(SymTable->sh_type == ELF::SHT_SYMTAB || - SymTable->sh_type == ELF::SHT_DYNSYM); - - auto SectionsOrErr = EF.sections(); - if (!SectionsOrErr) { - DRI.d.a = 0; - DRI.d.b = 0; - return DRI; - } - uintptr_t SHT = reinterpret_cast<uintptr_t>((*SectionsOrErr).begin()); - unsigned SymTableIndex = - (reinterpret_cast<uintptr_t>(SymTable) - SHT) / sizeof(Elf_Shdr); - - DRI.d.a = SymTableIndex; - DRI.d.b = SymbolNum; - return DRI; - } - - const Elf_Shdr *toELFShdrIter(DataRefImpl Sec) const { - return reinterpret_cast<const Elf_Shdr *>(Sec.p); - } - - DataRefImpl toDRI(const Elf_Shdr *Sec) const { - DataRefImpl DRI; - DRI.p = reinterpret_cast<uintptr_t>(Sec); - return DRI; - } - - DataRefImpl toDRI(const Elf_Dyn *Dyn) const { - DataRefImpl DRI; - DRI.p = reinterpret_cast<uintptr_t>(Dyn); - return DRI; - } - - bool isExportedToOtherDSO(const Elf_Sym *ESym) const { - unsigned char Binding = ESym->getBinding(); - unsigned char Visibility = ESym->getVisibility(); - - // A symbol is exported if its binding is either GLOBAL or WEAK, and its - // visibility is either DEFAULT or PROTECTED. All other symbols are not - // exported. - return ( - (Binding == ELF::STB_GLOBAL || Binding == ELF::STB_WEAK || - Binding == ELF::STB_GNU_UNIQUE) && - (Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_PROTECTED)); - } - - Error getBuildAttributes(ELFAttributeParser &Attributes) const override { - auto SectionsOrErr = EF.sections(); - if (!SectionsOrErr) - return SectionsOrErr.takeError(); - - for (const Elf_Shdr &Sec : *SectionsOrErr) { - if (Sec.sh_type == ELF::SHT_ARM_ATTRIBUTES || - Sec.sh_type == ELF::SHT_RISCV_ATTRIBUTES) { + void moveSymbolNext(DataRefImpl &Symb) const override; + Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; + Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; + uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; + uint32_t getSymbolAlignment(DataRefImpl Symb) const override; + uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; + Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override; + uint8_t getSymbolBinding(DataRefImpl Symb) const override; + uint8_t getSymbolOther(DataRefImpl Symb) const override; + uint8_t getSymbolELFType(DataRefImpl Symb) const override; + Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; + Expected<section_iterator> getSymbolSection(const Elf_Sym *Symb, + const Elf_Shdr *SymTab) const; + Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; + + void moveSectionNext(DataRefImpl &Sec) const override; + Expected<StringRef> getSectionName(DataRefImpl Sec) const override; + uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionIndex(DataRefImpl Sec) const override; + uint64_t getSectionSize(DataRefImpl Sec) const override; + Expected<ArrayRef<uint8_t>> + getSectionContents(DataRefImpl Sec) const override; + uint64_t getSectionAlignment(DataRefImpl Sec) const override; + bool isSectionCompressed(DataRefImpl Sec) const override; + bool isSectionText(DataRefImpl Sec) const override; + bool isSectionData(DataRefImpl Sec) const override; + bool isSectionBSS(DataRefImpl Sec) const override; + bool isSectionVirtual(DataRefImpl Sec) const override; + bool isBerkeleyText(DataRefImpl Sec) const override; + bool isBerkeleyData(DataRefImpl Sec) const override; + bool isDebugSection(StringRef SectionName) const override; + relocation_iterator section_rel_begin(DataRefImpl Sec) const override; + relocation_iterator section_rel_end(DataRefImpl Sec) const override; + std::vector<SectionRef> dynamic_relocation_sections() const override; + Expected<section_iterator> + getRelocatedSection(DataRefImpl Sec) const override; + + void moveRelocationNext(DataRefImpl &Rel) const override; + uint64_t getRelocationOffset(DataRefImpl Rel) const override; + symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + uint64_t getRelocationType(DataRefImpl Rel) const override; + void getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + + uint32_t getSectionType(DataRefImpl Sec) const override; + uint64_t getSectionFlags(DataRefImpl Sec) const override; + uint64_t getSectionOffset(DataRefImpl Sec) const override; + StringRef getRelocationTypeName(uint32_t Type) const; + + DataRefImpl toDRI(const Elf_Shdr *SymTable, unsigned SymbolNum) const { + DataRefImpl DRI; + if (!SymTable) { + DRI.d.a = 0; + DRI.d.b = 0; + return DRI; + } + assert(SymTable->sh_type == ELF::SHT_SYMTAB || + SymTable->sh_type == ELF::SHT_DYNSYM); + + auto SectionsOrErr = EF.sections(); + if (!SectionsOrErr) { + DRI.d.a = 0; + DRI.d.b = 0; + return DRI; + } + uintptr_t SHT = reinterpret_cast<uintptr_t>((*SectionsOrErr).begin()); + unsigned SymTableIndex = + (reinterpret_cast<uintptr_t>(SymTable) - SHT) / sizeof(Elf_Shdr); + + DRI.d.a = SymTableIndex; + DRI.d.b = SymbolNum; + return DRI; + } + + const Elf_Shdr *toELFShdrIter(DataRefImpl Sec) const { + return reinterpret_cast<const Elf_Shdr *>(Sec.p); + } + + DataRefImpl toDRI(const Elf_Shdr *Sec) const { + DataRefImpl DRI; + DRI.p = reinterpret_cast<uintptr_t>(Sec); + return DRI; + } + + DataRefImpl toDRI(const Elf_Dyn *Dyn) const { + DataRefImpl DRI; + DRI.p = reinterpret_cast<uintptr_t>(Dyn); + return DRI; + } + + bool isExportedToOtherDSO(const Elf_Sym *ESym) const { + unsigned char Binding = ESym->getBinding(); + unsigned char Visibility = ESym->getVisibility(); + + // A symbol is exported if its binding is either GLOBAL or WEAK, and its + // visibility is either DEFAULT or PROTECTED. All other symbols are not + // exported. + return ( + (Binding == ELF::STB_GLOBAL || Binding == ELF::STB_WEAK || + Binding == ELF::STB_GNU_UNIQUE) && + (Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_PROTECTED)); + } + + Error getBuildAttributes(ELFAttributeParser &Attributes) const override { + auto SectionsOrErr = EF.sections(); + if (!SectionsOrErr) + return SectionsOrErr.takeError(); + + for (const Elf_Shdr &Sec : *SectionsOrErr) { + if (Sec.sh_type == ELF::SHT_ARM_ATTRIBUTES || + Sec.sh_type == ELF::SHT_RISCV_ATTRIBUTES) { auto ErrorOrContents = EF.getSectionContents(Sec); - if (!ErrorOrContents) - return ErrorOrContents.takeError(); - - auto Contents = ErrorOrContents.get(); - if (Contents[0] != ELFAttrs::Format_Version || Contents.size() == 1) - return Error::success(); - - if (Error E = Attributes.parse(Contents, ELFT::TargetEndianness)) - return E; - break; - } - } - return Error::success(); - } - - // This flag is used for classof, to distinguish ELFObjectFile from - // its subclass. If more subclasses will be created, this flag will - // have to become an enum. - bool isDyldELFObject; - -public: - ELFObjectFile(ELFObjectFile<ELFT> &&Other); + if (!ErrorOrContents) + return ErrorOrContents.takeError(); + + auto Contents = ErrorOrContents.get(); + if (Contents[0] != ELFAttrs::Format_Version || Contents.size() == 1) + return Error::success(); + + if (Error E = Attributes.parse(Contents, ELFT::TargetEndianness)) + return E; + break; + } + } + return Error::success(); + } + + // This flag is used for classof, to distinguish ELFObjectFile from + // its subclass. If more subclasses will be created, this flag will + // have to become an enum. + bool isDyldELFObject; + +public: + ELFObjectFile(ELFObjectFile<ELFT> &&Other); static Expected<ELFObjectFile<ELFT>> create(MemoryBufferRef Object, bool InitContent = true); - - const Elf_Rel *getRel(DataRefImpl Rel) const; - const Elf_Rela *getRela(DataRefImpl Rela) const; - + + const Elf_Rel *getRel(DataRefImpl Rel) const; + const Elf_Rela *getRela(DataRefImpl Rela) const; + Expected<const Elf_Sym *> getSymbol(DataRefImpl Sym) const { return EF.template getEntry<Elf_Sym>(Sym.d.a, Sym.d.b); - } - + } + /// Get the relocation section that contains \a Rel. const Elf_Shdr *getRelSection(DataRefImpl Rel) const { auto RelSecOrErr = EF.getSection(Rel.d.a); @@ -418,51 +418,51 @@ public: return *RelSecOrErr; } - const Elf_Shdr *getSection(DataRefImpl Sec) const { - return reinterpret_cast<const Elf_Shdr *>(Sec.p); - } - - basic_symbol_iterator symbol_begin() const override; - basic_symbol_iterator symbol_end() const override; - - elf_symbol_iterator dynamic_symbol_begin() const; - elf_symbol_iterator dynamic_symbol_end() const; - - section_iterator section_begin() const override; - section_iterator section_end() const override; - - Expected<int64_t> getRelocationAddend(DataRefImpl Rel) const override; - - uint8_t getBytesInAddress() const override; - StringRef getFileFormatName() const override; - Triple::ArchType getArch() const override; - Expected<uint64_t> getStartAddress() const override; - + const Elf_Shdr *getSection(DataRefImpl Sec) const { + return reinterpret_cast<const Elf_Shdr *>(Sec.p); + } + + basic_symbol_iterator symbol_begin() const override; + basic_symbol_iterator symbol_end() const override; + + elf_symbol_iterator dynamic_symbol_begin() const; + elf_symbol_iterator dynamic_symbol_end() const; + + section_iterator section_begin() const override; + section_iterator section_end() const override; + + Expected<int64_t> getRelocationAddend(DataRefImpl Rel) const override; + + uint8_t getBytesInAddress() const override; + StringRef getFileFormatName() const override; + Triple::ArchType getArch() const override; + Expected<uint64_t> getStartAddress() const override; + unsigned getPlatformFlags() const override { return EF.getHeader().e_flags; } - + const ELFFile<ELFT> &getELFFile() const { return EF; } - - bool isDyldType() const { return isDyldELFObject; } - static bool classof(const Binary *v) { - return v->getType() == getELFType(ELFT::TargetEndianness == support::little, - ELFT::Is64Bits); - } - - elf_symbol_iterator_range getDynamicSymbolIterators() const override; - - bool isRelocatableObject() const override; -}; - -using ELF32LEObjectFile = ELFObjectFile<ELF32LE>; -using ELF64LEObjectFile = ELFObjectFile<ELF64LE>; -using ELF32BEObjectFile = ELFObjectFile<ELF32BE>; -using ELF64BEObjectFile = ELFObjectFile<ELF64BE>; - -template <class ELFT> -void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Sym) const { - ++Sym.d.b; -} - + + bool isDyldType() const { return isDyldELFObject; } + static bool classof(const Binary *v) { + return v->getType() == getELFType(ELFT::TargetEndianness == support::little, + ELFT::Is64Bits); + } + + elf_symbol_iterator_range getDynamicSymbolIterators() const override; + + bool isRelocatableObject() const override; +}; + +using ELF32LEObjectFile = ELFObjectFile<ELF32LE>; +using ELF64LEObjectFile = ELFObjectFile<ELF64LE>; +using ELF32BEObjectFile = ELFObjectFile<ELF32BE>; +using ELF64BEObjectFile = ELFObjectFile<ELF64BE>; + +template <class ELFT> +void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Sym) const { + ++Sym.d.b; +} + template <class ELFT> Error ELFObjectFile<ELFT>::initContent() { auto SectionsOrErr = EF.sections(); if (!SectionsOrErr) @@ -492,94 +492,94 @@ template <class ELFT> Error ELFObjectFile<ELFT>::initContent() { return Error::success(); } -template <class ELFT> -Expected<StringRef> ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Sym) const { +template <class ELFT> +Expected<StringRef> ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Sym) const { Expected<const Elf_Sym *> SymOrErr = getSymbol(Sym); if (!SymOrErr) return SymOrErr.takeError(); - auto SymTabOrErr = EF.getSection(Sym.d.a); - if (!SymTabOrErr) - return SymTabOrErr.takeError(); - const Elf_Shdr *SymTableSec = *SymTabOrErr; - auto StrTabOrErr = EF.getSection(SymTableSec->sh_link); - if (!StrTabOrErr) - return StrTabOrErr.takeError(); - const Elf_Shdr *StringTableSec = *StrTabOrErr; + auto SymTabOrErr = EF.getSection(Sym.d.a); + if (!SymTabOrErr) + return SymTabOrErr.takeError(); + const Elf_Shdr *SymTableSec = *SymTabOrErr; + auto StrTabOrErr = EF.getSection(SymTableSec->sh_link); + if (!StrTabOrErr) + return StrTabOrErr.takeError(); + const Elf_Shdr *StringTableSec = *StrTabOrErr; auto SymStrTabOrErr = EF.getStringTable(*StringTableSec); - if (!SymStrTabOrErr) - return SymStrTabOrErr.takeError(); + if (!SymStrTabOrErr) + return SymStrTabOrErr.takeError(); Expected<StringRef> Name = (*SymOrErr)->getName(*SymStrTabOrErr); - if (Name && !Name->empty()) - return Name; - - // If the symbol name is empty use the section name. + if (Name && !Name->empty()) + return Name; + + // If the symbol name is empty use the section name. if ((*SymOrErr)->getType() == ELF::STT_SECTION) { - if (Expected<section_iterator> SecOrErr = getSymbolSection(Sym)) { - consumeError(Name.takeError()); - return (*SecOrErr)->getName(); - } - } - return Name; -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getSectionFlags(DataRefImpl Sec) const { - return getSection(Sec)->sh_flags; -} - -template <class ELFT> -uint32_t ELFObjectFile<ELFT>::getSectionType(DataRefImpl Sec) const { - return getSection(Sec)->sh_type; -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getSectionOffset(DataRefImpl Sec) const { - return getSection(Sec)->sh_offset; -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getSymbolValueImpl(DataRefImpl Symb) const { + if (Expected<section_iterator> SecOrErr = getSymbolSection(Sym)) { + consumeError(Name.takeError()); + return (*SecOrErr)->getName(); + } + } + return Name; +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getSectionFlags(DataRefImpl Sec) const { + return getSection(Sec)->sh_flags; +} + +template <class ELFT> +uint32_t ELFObjectFile<ELFT>::getSectionType(DataRefImpl Sec) const { + return getSection(Sec)->sh_type; +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getSectionOffset(DataRefImpl Sec) const { + return getSection(Sec)->sh_offset; +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getSymbolValueImpl(DataRefImpl Symb) const { Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb); if (!SymOrErr) report_fatal_error(SymOrErr.takeError()); uint64_t Ret = (*SymOrErr)->st_value; if ((*SymOrErr)->st_shndx == ELF::SHN_ABS) - return Ret; - + return Ret; + const Elf_Ehdr &Header = EF.getHeader(); - // Clear the ARM/Thumb or microMIPS indicator flag. + // Clear the ARM/Thumb or microMIPS indicator flag. if ((Header.e_machine == ELF::EM_ARM || Header.e_machine == ELF::EM_MIPS) && (*SymOrErr)->getType() == ELF::STT_FUNC) - Ret &= ~1; - - return Ret; -} - -template <class ELFT> -Expected<uint64_t> -ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb) const { - Expected<uint64_t> SymbolValueOrErr = getSymbolValue(Symb); - if (!SymbolValueOrErr) - // TODO: Test this error. - return SymbolValueOrErr.takeError(); - - uint64_t Result = *SymbolValueOrErr; + Ret &= ~1; + + return Ret; +} + +template <class ELFT> +Expected<uint64_t> +ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb) const { + Expected<uint64_t> SymbolValueOrErr = getSymbolValue(Symb); + if (!SymbolValueOrErr) + // TODO: Test this error. + return SymbolValueOrErr.takeError(); + + uint64_t Result = *SymbolValueOrErr; Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb); if (!SymOrErr) return SymOrErr.takeError(); switch ((*SymOrErr)->st_shndx) { - case ELF::SHN_COMMON: - case ELF::SHN_UNDEF: - case ELF::SHN_ABS: - return Result; - } - - auto SymTabOrErr = EF.getSection(Symb.d.a); - if (!SymTabOrErr) - return SymTabOrErr.takeError(); - + case ELF::SHN_COMMON: + case ELF::SHN_UNDEF: + case ELF::SHN_ABS: + return Result; + } + + auto SymTabOrErr = EF.getSection(Symb.d.a); + if (!SymTabOrErr) + return SymTabOrErr.takeError(); + if (EF.getHeader().e_type == ELF::ET_REL) { ArrayRef<Elf_Word> ShndxTable; if (DotSymtabShndxSec) { @@ -593,169 +593,169 @@ ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb) const { Expected<const Elf_Shdr *> SectionOrErr = EF.getSection(**SymOrErr, *SymTabOrErr, ShndxTable); - if (!SectionOrErr) - return SectionOrErr.takeError(); - const Elf_Shdr *Section = *SectionOrErr; - if (Section) - Result += Section->sh_addr; - } - - return Result; -} - -template <class ELFT> -uint32_t ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb) const { + if (!SectionOrErr) + return SectionOrErr.takeError(); + const Elf_Shdr *Section = *SectionOrErr; + if (Section) + Result += Section->sh_addr; + } + + return Result; +} + +template <class ELFT> +uint32_t ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb) const { Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb); if (!SymOrErr) report_fatal_error(SymOrErr.takeError()); if ((*SymOrErr)->st_shndx == ELF::SHN_COMMON) return (*SymOrErr)->st_value; - return 0; -} - -template <class ELFT> -uint16_t ELFObjectFile<ELFT>::getEMachine() const { + return 0; +} + +template <class ELFT> +uint16_t ELFObjectFile<ELFT>::getEMachine() const { return EF.getHeader().e_machine; -} - -template <class ELFT> uint16_t ELFObjectFile<ELFT>::getEType() const { +} + +template <class ELFT> uint16_t ELFObjectFile<ELFT>::getEType() const { return EF.getHeader().e_type; -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Sym) const { +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Sym) const { Expected<const Elf_Sym *> SymOrErr = getSymbol(Sym); if (!SymOrErr) report_fatal_error(SymOrErr.takeError()); return (*SymOrErr)->st_size; -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getCommonSymbolSizeImpl(DataRefImpl Symb) const { +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getCommonSymbolSizeImpl(DataRefImpl Symb) const { return getSymbolSize(Symb); -} - -template <class ELFT> -uint8_t ELFObjectFile<ELFT>::getSymbolBinding(DataRefImpl Symb) const { +} + +template <class ELFT> +uint8_t ELFObjectFile<ELFT>::getSymbolBinding(DataRefImpl Symb) const { Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb); if (!SymOrErr) report_fatal_error(SymOrErr.takeError()); return (*SymOrErr)->getBinding(); -} - -template <class ELFT> -uint8_t ELFObjectFile<ELFT>::getSymbolOther(DataRefImpl Symb) const { +} + +template <class ELFT> +uint8_t ELFObjectFile<ELFT>::getSymbolOther(DataRefImpl Symb) const { Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb); if (!SymOrErr) report_fatal_error(SymOrErr.takeError()); return (*SymOrErr)->st_other; -} - -template <class ELFT> -uint8_t ELFObjectFile<ELFT>::getSymbolELFType(DataRefImpl Symb) const { +} + +template <class ELFT> +uint8_t ELFObjectFile<ELFT>::getSymbolELFType(DataRefImpl Symb) const { Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb); if (!SymOrErr) report_fatal_error(SymOrErr.takeError()); return (*SymOrErr)->getType(); -} - -template <class ELFT> -Expected<SymbolRef::Type> -ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb) const { +} + +template <class ELFT> +Expected<SymbolRef::Type> +ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb) const { Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb); if (!SymOrErr) return SymOrErr.takeError(); - + switch ((*SymOrErr)->getType()) { - case ELF::STT_NOTYPE: - return SymbolRef::ST_Unknown; - case ELF::STT_SECTION: - return SymbolRef::ST_Debug; - case ELF::STT_FILE: - return SymbolRef::ST_File; - case ELF::STT_FUNC: - return SymbolRef::ST_Function; - case ELF::STT_OBJECT: - case ELF::STT_COMMON: - case ELF::STT_TLS: - return SymbolRef::ST_Data; - default: - return SymbolRef::ST_Other; - } -} - -template <class ELFT> -Expected<uint32_t> ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Sym) const { + case ELF::STT_NOTYPE: + return SymbolRef::ST_Unknown; + case ELF::STT_SECTION: + return SymbolRef::ST_Debug; + case ELF::STT_FILE: + return SymbolRef::ST_File; + case ELF::STT_FUNC: + return SymbolRef::ST_Function; + case ELF::STT_OBJECT: + case ELF::STT_COMMON: + case ELF::STT_TLS: + return SymbolRef::ST_Data; + default: + return SymbolRef::ST_Other; + } +} + +template <class ELFT> +Expected<uint32_t> ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Sym) const { Expected<const Elf_Sym *> SymOrErr = getSymbol(Sym); if (!SymOrErr) return SymOrErr.takeError(); - + const Elf_Sym *ESym = *SymOrErr; - uint32_t Result = SymbolRef::SF_None; - - if (ESym->getBinding() != ELF::STB_LOCAL) - Result |= SymbolRef::SF_Global; - - if (ESym->getBinding() == ELF::STB_WEAK) - Result |= SymbolRef::SF_Weak; - - if (ESym->st_shndx == ELF::SHN_ABS) - Result |= SymbolRef::SF_Absolute; - - if (ESym->getType() == ELF::STT_FILE || ESym->getType() == ELF::STT_SECTION) - Result |= SymbolRef::SF_FormatSpecific; - - if (Expected<typename ELFT::SymRange> SymbolsOrErr = - EF.symbols(DotSymtabSec)) { - // Set the SF_FormatSpecific flag for the 0-index null symbol. - if (ESym == SymbolsOrErr->begin()) - Result |= SymbolRef::SF_FormatSpecific; - } else - // TODO: Test this error. - return SymbolsOrErr.takeError(); - - if (Expected<typename ELFT::SymRange> SymbolsOrErr = - EF.symbols(DotDynSymSec)) { - // Set the SF_FormatSpecific flag for the 0-index null symbol. - if (ESym == SymbolsOrErr->begin()) - Result |= SymbolRef::SF_FormatSpecific; - } else - // TODO: Test this error. - return SymbolsOrErr.takeError(); - + uint32_t Result = SymbolRef::SF_None; + + if (ESym->getBinding() != ELF::STB_LOCAL) + Result |= SymbolRef::SF_Global; + + if (ESym->getBinding() == ELF::STB_WEAK) + Result |= SymbolRef::SF_Weak; + + if (ESym->st_shndx == ELF::SHN_ABS) + Result |= SymbolRef::SF_Absolute; + + if (ESym->getType() == ELF::STT_FILE || ESym->getType() == ELF::STT_SECTION) + Result |= SymbolRef::SF_FormatSpecific; + + if (Expected<typename ELFT::SymRange> SymbolsOrErr = + EF.symbols(DotSymtabSec)) { + // Set the SF_FormatSpecific flag for the 0-index null symbol. + if (ESym == SymbolsOrErr->begin()) + Result |= SymbolRef::SF_FormatSpecific; + } else + // TODO: Test this error. + return SymbolsOrErr.takeError(); + + if (Expected<typename ELFT::SymRange> SymbolsOrErr = + EF.symbols(DotDynSymSec)) { + // Set the SF_FormatSpecific flag for the 0-index null symbol. + if (ESym == SymbolsOrErr->begin()) + Result |= SymbolRef::SF_FormatSpecific; + } else + // TODO: Test this error. + return SymbolsOrErr.takeError(); + if (EF.getHeader().e_machine == ELF::EM_ARM) { - if (Expected<StringRef> NameOrErr = getSymbolName(Sym)) { - StringRef Name = *NameOrErr; - if (Name.startswith("$d") || Name.startswith("$t") || - Name.startswith("$a")) - Result |= SymbolRef::SF_FormatSpecific; - } else { - // TODO: Actually report errors helpfully. - consumeError(NameOrErr.takeError()); - } - if (ESym->getType() == ELF::STT_FUNC && (ESym->st_value & 1) == 1) - Result |= SymbolRef::SF_Thumb; - } - - if (ESym->st_shndx == ELF::SHN_UNDEF) - Result |= SymbolRef::SF_Undefined; - - if (ESym->getType() == ELF::STT_COMMON || ESym->st_shndx == ELF::SHN_COMMON) - Result |= SymbolRef::SF_Common; - - if (isExportedToOtherDSO(ESym)) - Result |= SymbolRef::SF_Exported; - - if (ESym->getVisibility() == ELF::STV_HIDDEN) - Result |= SymbolRef::SF_Hidden; - - return Result; -} - -template <class ELFT> -Expected<section_iterator> -ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym, - const Elf_Shdr *SymTab) const { + if (Expected<StringRef> NameOrErr = getSymbolName(Sym)) { + StringRef Name = *NameOrErr; + if (Name.startswith("$d") || Name.startswith("$t") || + Name.startswith("$a")) + Result |= SymbolRef::SF_FormatSpecific; + } else { + // TODO: Actually report errors helpfully. + consumeError(NameOrErr.takeError()); + } + if (ESym->getType() == ELF::STT_FUNC && (ESym->st_value & 1) == 1) + Result |= SymbolRef::SF_Thumb; + } + + if (ESym->st_shndx == ELF::SHN_UNDEF) + Result |= SymbolRef::SF_Undefined; + + if (ESym->getType() == ELF::STT_COMMON || ESym->st_shndx == ELF::SHN_COMMON) + Result |= SymbolRef::SF_Common; + + if (isExportedToOtherDSO(ESym)) + Result |= SymbolRef::SF_Exported; + + if (ESym->getVisibility() == ELF::STV_HIDDEN) + Result |= SymbolRef::SF_Hidden; + + return Result; +} + +template <class ELFT> +Expected<section_iterator> +ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym, + const Elf_Shdr *SymTab) const { ArrayRef<Elf_Word> ShndxTable; if (DotSymtabShndxSec) { // TODO: Test this error. @@ -767,550 +767,550 @@ ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym, } auto ESecOrErr = EF.getSection(*ESym, SymTab, ShndxTable); - if (!ESecOrErr) - return ESecOrErr.takeError(); - - const Elf_Shdr *ESec = *ESecOrErr; - if (!ESec) - return section_end(); - - DataRefImpl Sec; - Sec.p = reinterpret_cast<intptr_t>(ESec); - return section_iterator(SectionRef(Sec, this)); -} - -template <class ELFT> -Expected<section_iterator> -ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb) const { + if (!ESecOrErr) + return ESecOrErr.takeError(); + + const Elf_Shdr *ESec = *ESecOrErr; + if (!ESec) + return section_end(); + + DataRefImpl Sec; + Sec.p = reinterpret_cast<intptr_t>(ESec); + return section_iterator(SectionRef(Sec, this)); +} + +template <class ELFT> +Expected<section_iterator> +ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb) const { Expected<const Elf_Sym *> SymOrErr = getSymbol(Symb); if (!SymOrErr) return SymOrErr.takeError(); - auto SymTabOrErr = EF.getSection(Symb.d.a); - if (!SymTabOrErr) - return SymTabOrErr.takeError(); + auto SymTabOrErr = EF.getSection(Symb.d.a); + if (!SymTabOrErr) + return SymTabOrErr.takeError(); return getSymbolSection(*SymOrErr, *SymTabOrErr); -} - -template <class ELFT> -void ELFObjectFile<ELFT>::moveSectionNext(DataRefImpl &Sec) const { - const Elf_Shdr *ESec = getSection(Sec); - Sec = toDRI(++ESec); -} - -template <class ELFT> -Expected<StringRef> ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec) const { +} + +template <class ELFT> +void ELFObjectFile<ELFT>::moveSectionNext(DataRefImpl &Sec) const { + const Elf_Shdr *ESec = getSection(Sec); + Sec = toDRI(++ESec); +} + +template <class ELFT> +Expected<StringRef> ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec) const { return EF.getSectionName(*getSection(Sec)); -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getSectionAddress(DataRefImpl Sec) const { - return getSection(Sec)->sh_addr; -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getSectionIndex(DataRefImpl Sec) const { - auto SectionsOrErr = EF.sections(); - handleAllErrors(std::move(SectionsOrErr.takeError()), - [](const ErrorInfoBase &) { - llvm_unreachable("unable to get section index"); - }); - const Elf_Shdr *First = SectionsOrErr->begin(); - return getSection(Sec) - First; -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getSectionSize(DataRefImpl Sec) const { - return getSection(Sec)->sh_size; -} - -template <class ELFT> -Expected<ArrayRef<uint8_t>> -ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec) const { - const Elf_Shdr *EShdr = getSection(Sec); - if (EShdr->sh_type == ELF::SHT_NOBITS) - return makeArrayRef((const uint8_t *)base(), 0); - if (Error E = - checkOffset(getMemoryBufferRef(), - (uintptr_t)base() + EShdr->sh_offset, EShdr->sh_size)) - return std::move(E); - return makeArrayRef((const uint8_t *)base() + EShdr->sh_offset, - EShdr->sh_size); -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec) const { - return getSection(Sec)->sh_addralign; -} - -template <class ELFT> -bool ELFObjectFile<ELFT>::isSectionCompressed(DataRefImpl Sec) const { - return getSection(Sec)->sh_flags & ELF::SHF_COMPRESSED; -} - -template <class ELFT> -bool ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec) const { - return getSection(Sec)->sh_flags & ELF::SHF_EXECINSTR; -} - -template <class ELFT> -bool ELFObjectFile<ELFT>::isSectionData(DataRefImpl Sec) const { - const Elf_Shdr *EShdr = getSection(Sec); - return EShdr->sh_type == ELF::SHT_PROGBITS && - EShdr->sh_flags & ELF::SHF_ALLOC && - !(EShdr->sh_flags & ELF::SHF_EXECINSTR); -} - -template <class ELFT> -bool ELFObjectFile<ELFT>::isSectionBSS(DataRefImpl Sec) const { - const Elf_Shdr *EShdr = getSection(Sec); - return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && - EShdr->sh_type == ELF::SHT_NOBITS; -} - -template <class ELFT> -std::vector<SectionRef> -ELFObjectFile<ELFT>::dynamic_relocation_sections() const { - std::vector<SectionRef> Res; - std::vector<uintptr_t> Offsets; - - auto SectionsOrErr = EF.sections(); - if (!SectionsOrErr) - return Res; - - for (const Elf_Shdr &Sec : *SectionsOrErr) { - if (Sec.sh_type != ELF::SHT_DYNAMIC) - continue; - Elf_Dyn *Dynamic = - reinterpret_cast<Elf_Dyn *>((uintptr_t)base() + Sec.sh_offset); - for (; Dynamic->d_tag != ELF::DT_NULL; Dynamic++) { - if (Dynamic->d_tag == ELF::DT_REL || Dynamic->d_tag == ELF::DT_RELA || - Dynamic->d_tag == ELF::DT_JMPREL) { - Offsets.push_back(Dynamic->d_un.d_val); - } - } - } - for (const Elf_Shdr &Sec : *SectionsOrErr) { - if (is_contained(Offsets, Sec.sh_addr)) - Res.emplace_back(toDRI(&Sec), this); - } - return Res; -} - -template <class ELFT> -bool ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec) const { - return getSection(Sec)->sh_type == ELF::SHT_NOBITS; -} - -template <class ELFT> -bool ELFObjectFile<ELFT>::isBerkeleyText(DataRefImpl Sec) const { - return getSection(Sec)->sh_flags & ELF::SHF_ALLOC && - (getSection(Sec)->sh_flags & ELF::SHF_EXECINSTR || - !(getSection(Sec)->sh_flags & ELF::SHF_WRITE)); -} - -template <class ELFT> -bool ELFObjectFile<ELFT>::isBerkeleyData(DataRefImpl Sec) const { - const Elf_Shdr *EShdr = getSection(Sec); - return !isBerkeleyText(Sec) && EShdr->sh_type != ELF::SHT_NOBITS && - EShdr->sh_flags & ELF::SHF_ALLOC; -} - -template <class ELFT> -bool ELFObjectFile<ELFT>::isDebugSection(StringRef SectionName) const { - return SectionName.startswith(".debug") || - SectionName.startswith(".zdebug") || SectionName == ".gdb_index"; -} - -template <class ELFT> -relocation_iterator -ELFObjectFile<ELFT>::section_rel_begin(DataRefImpl Sec) const { - DataRefImpl RelData; - auto SectionsOrErr = EF.sections(); - if (!SectionsOrErr) - return relocation_iterator(RelocationRef()); - uintptr_t SHT = reinterpret_cast<uintptr_t>((*SectionsOrErr).begin()); +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getSectionAddress(DataRefImpl Sec) const { + return getSection(Sec)->sh_addr; +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getSectionIndex(DataRefImpl Sec) const { + auto SectionsOrErr = EF.sections(); + handleAllErrors(std::move(SectionsOrErr.takeError()), + [](const ErrorInfoBase &) { + llvm_unreachable("unable to get section index"); + }); + const Elf_Shdr *First = SectionsOrErr->begin(); + return getSection(Sec) - First; +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getSectionSize(DataRefImpl Sec) const { + return getSection(Sec)->sh_size; +} + +template <class ELFT> +Expected<ArrayRef<uint8_t>> +ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec) const { + const Elf_Shdr *EShdr = getSection(Sec); + if (EShdr->sh_type == ELF::SHT_NOBITS) + return makeArrayRef((const uint8_t *)base(), 0); + if (Error E = + checkOffset(getMemoryBufferRef(), + (uintptr_t)base() + EShdr->sh_offset, EShdr->sh_size)) + return std::move(E); + return makeArrayRef((const uint8_t *)base() + EShdr->sh_offset, + EShdr->sh_size); +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec) const { + return getSection(Sec)->sh_addralign; +} + +template <class ELFT> +bool ELFObjectFile<ELFT>::isSectionCompressed(DataRefImpl Sec) const { + return getSection(Sec)->sh_flags & ELF::SHF_COMPRESSED; +} + +template <class ELFT> +bool ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec) const { + return getSection(Sec)->sh_flags & ELF::SHF_EXECINSTR; +} + +template <class ELFT> +bool ELFObjectFile<ELFT>::isSectionData(DataRefImpl Sec) const { + const Elf_Shdr *EShdr = getSection(Sec); + return EShdr->sh_type == ELF::SHT_PROGBITS && + EShdr->sh_flags & ELF::SHF_ALLOC && + !(EShdr->sh_flags & ELF::SHF_EXECINSTR); +} + +template <class ELFT> +bool ELFObjectFile<ELFT>::isSectionBSS(DataRefImpl Sec) const { + const Elf_Shdr *EShdr = getSection(Sec); + return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && + EShdr->sh_type == ELF::SHT_NOBITS; +} + +template <class ELFT> +std::vector<SectionRef> +ELFObjectFile<ELFT>::dynamic_relocation_sections() const { + std::vector<SectionRef> Res; + std::vector<uintptr_t> Offsets; + + auto SectionsOrErr = EF.sections(); + if (!SectionsOrErr) + return Res; + + for (const Elf_Shdr &Sec : *SectionsOrErr) { + if (Sec.sh_type != ELF::SHT_DYNAMIC) + continue; + Elf_Dyn *Dynamic = + reinterpret_cast<Elf_Dyn *>((uintptr_t)base() + Sec.sh_offset); + for (; Dynamic->d_tag != ELF::DT_NULL; Dynamic++) { + if (Dynamic->d_tag == ELF::DT_REL || Dynamic->d_tag == ELF::DT_RELA || + Dynamic->d_tag == ELF::DT_JMPREL) { + Offsets.push_back(Dynamic->d_un.d_val); + } + } + } + for (const Elf_Shdr &Sec : *SectionsOrErr) { + if (is_contained(Offsets, Sec.sh_addr)) + Res.emplace_back(toDRI(&Sec), this); + } + return Res; +} + +template <class ELFT> +bool ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec) const { + return getSection(Sec)->sh_type == ELF::SHT_NOBITS; +} + +template <class ELFT> +bool ELFObjectFile<ELFT>::isBerkeleyText(DataRefImpl Sec) const { + return getSection(Sec)->sh_flags & ELF::SHF_ALLOC && + (getSection(Sec)->sh_flags & ELF::SHF_EXECINSTR || + !(getSection(Sec)->sh_flags & ELF::SHF_WRITE)); +} + +template <class ELFT> +bool ELFObjectFile<ELFT>::isBerkeleyData(DataRefImpl Sec) const { + const Elf_Shdr *EShdr = getSection(Sec); + return !isBerkeleyText(Sec) && EShdr->sh_type != ELF::SHT_NOBITS && + EShdr->sh_flags & ELF::SHF_ALLOC; +} + +template <class ELFT> +bool ELFObjectFile<ELFT>::isDebugSection(StringRef SectionName) const { + return SectionName.startswith(".debug") || + SectionName.startswith(".zdebug") || SectionName == ".gdb_index"; +} + +template <class ELFT> +relocation_iterator +ELFObjectFile<ELFT>::section_rel_begin(DataRefImpl Sec) const { + DataRefImpl RelData; + auto SectionsOrErr = EF.sections(); + if (!SectionsOrErr) + return relocation_iterator(RelocationRef()); + uintptr_t SHT = reinterpret_cast<uintptr_t>((*SectionsOrErr).begin()); RelData.d.a = (Sec.p - SHT) / EF.getHeader().e_shentsize; - RelData.d.b = 0; - return relocation_iterator(RelocationRef(RelData, this)); -} - -template <class ELFT> -relocation_iterator -ELFObjectFile<ELFT>::section_rel_end(DataRefImpl Sec) const { - const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p); - relocation_iterator Begin = section_rel_begin(Sec); - if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL) - return Begin; - DataRefImpl RelData = Begin->getRawDataRefImpl(); - const Elf_Shdr *RelSec = getRelSection(RelData); - - // Error check sh_link here so that getRelocationSymbol can just use it. - auto SymSecOrErr = EF.getSection(RelSec->sh_link); - if (!SymSecOrErr) - report_fatal_error(errorToErrorCode(SymSecOrErr.takeError()).message()); - - RelData.d.b += S->sh_size / S->sh_entsize; - return relocation_iterator(RelocationRef(RelData, this)); -} - -template <class ELFT> -Expected<section_iterator> -ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const { + RelData.d.b = 0; + return relocation_iterator(RelocationRef(RelData, this)); +} + +template <class ELFT> +relocation_iterator +ELFObjectFile<ELFT>::section_rel_end(DataRefImpl Sec) const { + const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p); + relocation_iterator Begin = section_rel_begin(Sec); + if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL) + return Begin; + DataRefImpl RelData = Begin->getRawDataRefImpl(); + const Elf_Shdr *RelSec = getRelSection(RelData); + + // Error check sh_link here so that getRelocationSymbol can just use it. + auto SymSecOrErr = EF.getSection(RelSec->sh_link); + if (!SymSecOrErr) + report_fatal_error(errorToErrorCode(SymSecOrErr.takeError()).message()); + + RelData.d.b += S->sh_size / S->sh_entsize; + return relocation_iterator(RelocationRef(RelData, this)); +} + +template <class ELFT> +Expected<section_iterator> +ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const { if (EF.getHeader().e_type != ELF::ET_REL) - return section_end(); - - const Elf_Shdr *EShdr = getSection(Sec); - uintX_t Type = EShdr->sh_type; - if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA) - return section_end(); - - Expected<const Elf_Shdr *> SecOrErr = EF.getSection(EShdr->sh_info); - if (!SecOrErr) - return SecOrErr.takeError(); - return section_iterator(SectionRef(toDRI(*SecOrErr), this)); -} - -// Relocations -template <class ELFT> -void ELFObjectFile<ELFT>::moveRelocationNext(DataRefImpl &Rel) const { - ++Rel.d.b; -} - -template <class ELFT> -symbol_iterator -ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const { - uint32_t symbolIdx; - const Elf_Shdr *sec = getRelSection(Rel); - if (sec->sh_type == ELF::SHT_REL) - symbolIdx = getRel(Rel)->getSymbol(EF.isMips64EL()); - else - symbolIdx = getRela(Rel)->getSymbol(EF.isMips64EL()); - if (!symbolIdx) - return symbol_end(); - - // FIXME: error check symbolIdx - DataRefImpl SymbolData; - SymbolData.d.a = sec->sh_link; - SymbolData.d.b = symbolIdx; - return symbol_iterator(SymbolRef(SymbolData, this)); -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel) const { - const Elf_Shdr *sec = getRelSection(Rel); - if (sec->sh_type == ELF::SHT_REL) - return getRel(Rel)->r_offset; - - return getRela(Rel)->r_offset; -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel) const { - const Elf_Shdr *sec = getRelSection(Rel); - if (sec->sh_type == ELF::SHT_REL) - return getRel(Rel)->getType(EF.isMips64EL()); - else - return getRela(Rel)->getType(EF.isMips64EL()); -} - -template <class ELFT> -StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const { + return section_end(); + + const Elf_Shdr *EShdr = getSection(Sec); + uintX_t Type = EShdr->sh_type; + if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA) + return section_end(); + + Expected<const Elf_Shdr *> SecOrErr = EF.getSection(EShdr->sh_info); + if (!SecOrErr) + return SecOrErr.takeError(); + return section_iterator(SectionRef(toDRI(*SecOrErr), this)); +} + +// Relocations +template <class ELFT> +void ELFObjectFile<ELFT>::moveRelocationNext(DataRefImpl &Rel) const { + ++Rel.d.b; +} + +template <class ELFT> +symbol_iterator +ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const { + uint32_t symbolIdx; + const Elf_Shdr *sec = getRelSection(Rel); + if (sec->sh_type == ELF::SHT_REL) + symbolIdx = getRel(Rel)->getSymbol(EF.isMips64EL()); + else + symbolIdx = getRela(Rel)->getSymbol(EF.isMips64EL()); + if (!symbolIdx) + return symbol_end(); + + // FIXME: error check symbolIdx + DataRefImpl SymbolData; + SymbolData.d.a = sec->sh_link; + SymbolData.d.b = symbolIdx; + return symbol_iterator(SymbolRef(SymbolData, this)); +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel) const { + const Elf_Shdr *sec = getRelSection(Rel); + if (sec->sh_type == ELF::SHT_REL) + return getRel(Rel)->r_offset; + + return getRela(Rel)->r_offset; +} + +template <class ELFT> +uint64_t ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel) const { + const Elf_Shdr *sec = getRelSection(Rel); + if (sec->sh_type == ELF::SHT_REL) + return getRel(Rel)->getType(EF.isMips64EL()); + else + return getRela(Rel)->getType(EF.isMips64EL()); +} + +template <class ELFT> +StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const { return getELFRelocationTypeName(EF.getHeader().e_machine, Type); -} - -template <class ELFT> -void ELFObjectFile<ELFT>::getRelocationTypeName( - DataRefImpl Rel, SmallVectorImpl<char> &Result) const { - uint32_t type = getRelocationType(Rel); - EF.getRelocationTypeName(type, Result); -} - -template <class ELFT> -Expected<int64_t> -ELFObjectFile<ELFT>::getRelocationAddend(DataRefImpl Rel) const { - if (getRelSection(Rel)->sh_type != ELF::SHT_RELA) - return createError("Section is not SHT_RELA"); - return (int64_t)getRela(Rel)->r_addend; -} - -template <class ELFT> -const typename ELFObjectFile<ELFT>::Elf_Rel * -ELFObjectFile<ELFT>::getRel(DataRefImpl Rel) const { - assert(getRelSection(Rel)->sh_type == ELF::SHT_REL); - auto Ret = EF.template getEntry<Elf_Rel>(Rel.d.a, Rel.d.b); - if (!Ret) - report_fatal_error(errorToErrorCode(Ret.takeError()).message()); - return *Ret; -} - -template <class ELFT> -const typename ELFObjectFile<ELFT>::Elf_Rela * -ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const { - assert(getRelSection(Rela)->sh_type == ELF::SHT_RELA); - auto Ret = EF.template getEntry<Elf_Rela>(Rela.d.a, Rela.d.b); - if (!Ret) - report_fatal_error(errorToErrorCode(Ret.takeError()).message()); - return *Ret; -} - -template <class ELFT> -Expected<ELFObjectFile<ELFT>> +} + +template <class ELFT> +void ELFObjectFile<ELFT>::getRelocationTypeName( + DataRefImpl Rel, SmallVectorImpl<char> &Result) const { + uint32_t type = getRelocationType(Rel); + EF.getRelocationTypeName(type, Result); +} + +template <class ELFT> +Expected<int64_t> +ELFObjectFile<ELFT>::getRelocationAddend(DataRefImpl Rel) const { + if (getRelSection(Rel)->sh_type != ELF::SHT_RELA) + return createError("Section is not SHT_RELA"); + return (int64_t)getRela(Rel)->r_addend; +} + +template <class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Rel * +ELFObjectFile<ELFT>::getRel(DataRefImpl Rel) const { + assert(getRelSection(Rel)->sh_type == ELF::SHT_REL); + auto Ret = EF.template getEntry<Elf_Rel>(Rel.d.a, Rel.d.b); + if (!Ret) + report_fatal_error(errorToErrorCode(Ret.takeError()).message()); + return *Ret; +} + +template <class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Rela * +ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const { + assert(getRelSection(Rela)->sh_type == ELF::SHT_RELA); + auto Ret = EF.template getEntry<Elf_Rela>(Rela.d.a, Rela.d.b); + if (!Ret) + report_fatal_error(errorToErrorCode(Ret.takeError()).message()); + return *Ret; +} + +template <class ELFT> +Expected<ELFObjectFile<ELFT>> ELFObjectFile<ELFT>::create(MemoryBufferRef Object, bool InitContent) { - auto EFOrErr = ELFFile<ELFT>::create(Object.getBuffer()); - if (Error E = EFOrErr.takeError()) - return std::move(E); - + auto EFOrErr = ELFFile<ELFT>::create(Object.getBuffer()); + if (Error E = EFOrErr.takeError()) + return std::move(E); + ELFObjectFile<ELFT> Obj = {Object, std::move(*EFOrErr), nullptr, nullptr, nullptr}; if (InitContent) if (Error E = Obj.initContent()) return std::move(E); return std::move(Obj); -} - -template <class ELFT> -ELFObjectFile<ELFT>::ELFObjectFile(MemoryBufferRef Object, ELFFile<ELFT> EF, - const Elf_Shdr *DotDynSymSec, - const Elf_Shdr *DotSymtabSec, +} + +template <class ELFT> +ELFObjectFile<ELFT>::ELFObjectFile(MemoryBufferRef Object, ELFFile<ELFT> EF, + const Elf_Shdr *DotDynSymSec, + const Elf_Shdr *DotSymtabSec, const Elf_Shdr *DotSymtabShndx) - : ELFObjectFileBase( - getELFType(ELFT::TargetEndianness == support::little, ELFT::Is64Bits), - Object), - EF(EF), DotDynSymSec(DotDynSymSec), DotSymtabSec(DotSymtabSec), + : ELFObjectFileBase( + getELFType(ELFT::TargetEndianness == support::little, ELFT::Is64Bits), + Object), + EF(EF), DotDynSymSec(DotDynSymSec), DotSymtabSec(DotSymtabSec), DotSymtabShndxSec(DotSymtabShndx) {} - -template <class ELFT> -ELFObjectFile<ELFT>::ELFObjectFile(ELFObjectFile<ELFT> &&Other) - : ELFObjectFile(Other.Data, Other.EF, Other.DotDynSymSec, + +template <class ELFT> +ELFObjectFile<ELFT>::ELFObjectFile(ELFObjectFile<ELFT> &&Other) + : ELFObjectFile(Other.Data, Other.EF, Other.DotDynSymSec, Other.DotSymtabSec, Other.DotSymtabShndxSec) {} - -template <class ELFT> -basic_symbol_iterator ELFObjectFile<ELFT>::symbol_begin() const { - DataRefImpl Sym = - toDRI(DotSymtabSec, - DotSymtabSec && DotSymtabSec->sh_size >= sizeof(Elf_Sym) ? 1 : 0); - return basic_symbol_iterator(SymbolRef(Sym, this)); -} - -template <class ELFT> -basic_symbol_iterator ELFObjectFile<ELFT>::symbol_end() const { - const Elf_Shdr *SymTab = DotSymtabSec; - if (!SymTab) - return symbol_begin(); - DataRefImpl Sym = toDRI(SymTab, SymTab->sh_size / sizeof(Elf_Sym)); - return basic_symbol_iterator(SymbolRef(Sym, this)); -} - -template <class ELFT> -elf_symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_begin() const { - if (!DotDynSymSec || DotDynSymSec->sh_size < sizeof(Elf_Sym)) - // Ignore errors here where the dynsym is empty or sh_size less than the - // size of one symbol. These should be handled elsewhere. - return symbol_iterator(SymbolRef(toDRI(DotDynSymSec, 0), this)); - // Skip 0-index NULL symbol. - return symbol_iterator(SymbolRef(toDRI(DotDynSymSec, 1), this)); -} - -template <class ELFT> -elf_symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_end() const { - const Elf_Shdr *SymTab = DotDynSymSec; - if (!SymTab) - return dynamic_symbol_begin(); - DataRefImpl Sym = toDRI(SymTab, SymTab->sh_size / sizeof(Elf_Sym)); - return basic_symbol_iterator(SymbolRef(Sym, this)); -} - -template <class ELFT> -section_iterator ELFObjectFile<ELFT>::section_begin() const { - auto SectionsOrErr = EF.sections(); - if (!SectionsOrErr) - return section_iterator(SectionRef()); - return section_iterator(SectionRef(toDRI((*SectionsOrErr).begin()), this)); -} - -template <class ELFT> -section_iterator ELFObjectFile<ELFT>::section_end() const { - auto SectionsOrErr = EF.sections(); - if (!SectionsOrErr) - return section_iterator(SectionRef()); - return section_iterator(SectionRef(toDRI((*SectionsOrErr).end()), this)); -} - -template <class ELFT> -uint8_t ELFObjectFile<ELFT>::getBytesInAddress() const { - return ELFT::Is64Bits ? 8 : 4; -} - -template <class ELFT> -StringRef ELFObjectFile<ELFT>::getFileFormatName() const { - bool IsLittleEndian = ELFT::TargetEndianness == support::little; + +template <class ELFT> +basic_symbol_iterator ELFObjectFile<ELFT>::symbol_begin() const { + DataRefImpl Sym = + toDRI(DotSymtabSec, + DotSymtabSec && DotSymtabSec->sh_size >= sizeof(Elf_Sym) ? 1 : 0); + return basic_symbol_iterator(SymbolRef(Sym, this)); +} + +template <class ELFT> +basic_symbol_iterator ELFObjectFile<ELFT>::symbol_end() const { + const Elf_Shdr *SymTab = DotSymtabSec; + if (!SymTab) + return symbol_begin(); + DataRefImpl Sym = toDRI(SymTab, SymTab->sh_size / sizeof(Elf_Sym)); + return basic_symbol_iterator(SymbolRef(Sym, this)); +} + +template <class ELFT> +elf_symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_begin() const { + if (!DotDynSymSec || DotDynSymSec->sh_size < sizeof(Elf_Sym)) + // Ignore errors here where the dynsym is empty or sh_size less than the + // size of one symbol. These should be handled elsewhere. + return symbol_iterator(SymbolRef(toDRI(DotDynSymSec, 0), this)); + // Skip 0-index NULL symbol. + return symbol_iterator(SymbolRef(toDRI(DotDynSymSec, 1), this)); +} + +template <class ELFT> +elf_symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_end() const { + const Elf_Shdr *SymTab = DotDynSymSec; + if (!SymTab) + return dynamic_symbol_begin(); + DataRefImpl Sym = toDRI(SymTab, SymTab->sh_size / sizeof(Elf_Sym)); + return basic_symbol_iterator(SymbolRef(Sym, this)); +} + +template <class ELFT> +section_iterator ELFObjectFile<ELFT>::section_begin() const { + auto SectionsOrErr = EF.sections(); + if (!SectionsOrErr) + return section_iterator(SectionRef()); + return section_iterator(SectionRef(toDRI((*SectionsOrErr).begin()), this)); +} + +template <class ELFT> +section_iterator ELFObjectFile<ELFT>::section_end() const { + auto SectionsOrErr = EF.sections(); + if (!SectionsOrErr) + return section_iterator(SectionRef()); + return section_iterator(SectionRef(toDRI((*SectionsOrErr).end()), this)); +} + +template <class ELFT> +uint8_t ELFObjectFile<ELFT>::getBytesInAddress() const { + return ELFT::Is64Bits ? 8 : 4; +} + +template <class ELFT> +StringRef ELFObjectFile<ELFT>::getFileFormatName() const { + bool IsLittleEndian = ELFT::TargetEndianness == support::little; switch (EF.getHeader().e_ident[ELF::EI_CLASS]) { - case ELF::ELFCLASS32: + case ELF::ELFCLASS32: switch (EF.getHeader().e_machine) { - case ELF::EM_386: - return "elf32-i386"; - case ELF::EM_IAMCU: - return "elf32-iamcu"; - case ELF::EM_X86_64: - return "elf32-x86-64"; - case ELF::EM_ARM: - return (IsLittleEndian ? "elf32-littlearm" : "elf32-bigarm"); - case ELF::EM_AVR: - return "elf32-avr"; - case ELF::EM_HEXAGON: - return "elf32-hexagon"; - case ELF::EM_LANAI: - return "elf32-lanai"; - case ELF::EM_MIPS: - return "elf32-mips"; - case ELF::EM_MSP430: - return "elf32-msp430"; - case ELF::EM_PPC: + case ELF::EM_386: + return "elf32-i386"; + case ELF::EM_IAMCU: + return "elf32-iamcu"; + case ELF::EM_X86_64: + return "elf32-x86-64"; + case ELF::EM_ARM: + return (IsLittleEndian ? "elf32-littlearm" : "elf32-bigarm"); + case ELF::EM_AVR: + return "elf32-avr"; + case ELF::EM_HEXAGON: + return "elf32-hexagon"; + case ELF::EM_LANAI: + return "elf32-lanai"; + case ELF::EM_MIPS: + return "elf32-mips"; + case ELF::EM_MSP430: + return "elf32-msp430"; + case ELF::EM_PPC: return (IsLittleEndian ? "elf32-powerpcle" : "elf32-powerpc"); - case ELF::EM_RISCV: - return "elf32-littleriscv"; + case ELF::EM_RISCV: + return "elf32-littleriscv"; case ELF::EM_CSKY: return "elf32-csky"; - case ELF::EM_SPARC: - case ELF::EM_SPARC32PLUS: - return "elf32-sparc"; - case ELF::EM_AMDGPU: - return "elf32-amdgpu"; - default: - return "elf32-unknown"; - } - case ELF::ELFCLASS64: + case ELF::EM_SPARC: + case ELF::EM_SPARC32PLUS: + return "elf32-sparc"; + case ELF::EM_AMDGPU: + return "elf32-amdgpu"; + default: + return "elf32-unknown"; + } + case ELF::ELFCLASS64: switch (EF.getHeader().e_machine) { - case ELF::EM_386: - return "elf64-i386"; - case ELF::EM_X86_64: - return "elf64-x86-64"; - case ELF::EM_AARCH64: - return (IsLittleEndian ? "elf64-littleaarch64" : "elf64-bigaarch64"); - case ELF::EM_PPC64: - return (IsLittleEndian ? "elf64-powerpcle" : "elf64-powerpc"); - case ELF::EM_RISCV: - return "elf64-littleriscv"; - case ELF::EM_S390: - return "elf64-s390"; - case ELF::EM_SPARCV9: - return "elf64-sparc"; - case ELF::EM_MIPS: - return "elf64-mips"; - case ELF::EM_AMDGPU: - return "elf64-amdgpu"; - case ELF::EM_BPF: - return "elf64-bpf"; - case ELF::EM_VE: - return "elf64-ve"; - default: - return "elf64-unknown"; - } - default: - // FIXME: Proper error handling. - report_fatal_error("Invalid ELFCLASS!"); - } -} - -template <class ELFT> Triple::ArchType ELFObjectFile<ELFT>::getArch() const { - bool IsLittleEndian = ELFT::TargetEndianness == support::little; + case ELF::EM_386: + return "elf64-i386"; + case ELF::EM_X86_64: + return "elf64-x86-64"; + case ELF::EM_AARCH64: + return (IsLittleEndian ? "elf64-littleaarch64" : "elf64-bigaarch64"); + case ELF::EM_PPC64: + return (IsLittleEndian ? "elf64-powerpcle" : "elf64-powerpc"); + case ELF::EM_RISCV: + return "elf64-littleriscv"; + case ELF::EM_S390: + return "elf64-s390"; + case ELF::EM_SPARCV9: + return "elf64-sparc"; + case ELF::EM_MIPS: + return "elf64-mips"; + case ELF::EM_AMDGPU: + return "elf64-amdgpu"; + case ELF::EM_BPF: + return "elf64-bpf"; + case ELF::EM_VE: + return "elf64-ve"; + default: + return "elf64-unknown"; + } + default: + // FIXME: Proper error handling. + report_fatal_error("Invalid ELFCLASS!"); + } +} + +template <class ELFT> Triple::ArchType ELFObjectFile<ELFT>::getArch() const { + bool IsLittleEndian = ELFT::TargetEndianness == support::little; switch (EF.getHeader().e_machine) { - case ELF::EM_386: - case ELF::EM_IAMCU: - return Triple::x86; - case ELF::EM_X86_64: - return Triple::x86_64; - case ELF::EM_AARCH64: - return IsLittleEndian ? Triple::aarch64 : Triple::aarch64_be; - case ELF::EM_ARM: - return Triple::arm; - case ELF::EM_AVR: - return Triple::avr; - case ELF::EM_HEXAGON: - return Triple::hexagon; - case ELF::EM_LANAI: - return Triple::lanai; - case ELF::EM_MIPS: + case ELF::EM_386: + case ELF::EM_IAMCU: + return Triple::x86; + case ELF::EM_X86_64: + return Triple::x86_64; + case ELF::EM_AARCH64: + return IsLittleEndian ? Triple::aarch64 : Triple::aarch64_be; + case ELF::EM_ARM: + return Triple::arm; + case ELF::EM_AVR: + return Triple::avr; + case ELF::EM_HEXAGON: + return Triple::hexagon; + case ELF::EM_LANAI: + return Triple::lanai; + case ELF::EM_MIPS: switch (EF.getHeader().e_ident[ELF::EI_CLASS]) { - case ELF::ELFCLASS32: - return IsLittleEndian ? Triple::mipsel : Triple::mips; - case ELF::ELFCLASS64: - return IsLittleEndian ? Triple::mips64el : Triple::mips64; - default: - report_fatal_error("Invalid ELFCLASS!"); - } - case ELF::EM_MSP430: - return Triple::msp430; - case ELF::EM_PPC: + case ELF::ELFCLASS32: + return IsLittleEndian ? Triple::mipsel : Triple::mips; + case ELF::ELFCLASS64: + return IsLittleEndian ? Triple::mips64el : Triple::mips64; + default: + report_fatal_error("Invalid ELFCLASS!"); + } + case ELF::EM_MSP430: + return Triple::msp430; + case ELF::EM_PPC: return IsLittleEndian ? Triple::ppcle : Triple::ppc; - case ELF::EM_PPC64: - return IsLittleEndian ? Triple::ppc64le : Triple::ppc64; - case ELF::EM_RISCV: + case ELF::EM_PPC64: + return IsLittleEndian ? Triple::ppc64le : Triple::ppc64; + case ELF::EM_RISCV: switch (EF.getHeader().e_ident[ELF::EI_CLASS]) { - case ELF::ELFCLASS32: - return Triple::riscv32; - case ELF::ELFCLASS64: - return Triple::riscv64; - default: - report_fatal_error("Invalid ELFCLASS!"); - } - case ELF::EM_S390: - return Triple::systemz; - - case ELF::EM_SPARC: - case ELF::EM_SPARC32PLUS: - return IsLittleEndian ? Triple::sparcel : Triple::sparc; - case ELF::EM_SPARCV9: - return Triple::sparcv9; - - case ELF::EM_AMDGPU: { - if (!IsLittleEndian) - return Triple::UnknownArch; - + case ELF::ELFCLASS32: + return Triple::riscv32; + case ELF::ELFCLASS64: + return Triple::riscv64; + default: + report_fatal_error("Invalid ELFCLASS!"); + } + case ELF::EM_S390: + return Triple::systemz; + + case ELF::EM_SPARC: + case ELF::EM_SPARC32PLUS: + return IsLittleEndian ? Triple::sparcel : Triple::sparc; + case ELF::EM_SPARCV9: + return Triple::sparcv9; + + case ELF::EM_AMDGPU: { + if (!IsLittleEndian) + return Triple::UnknownArch; + unsigned MACH = EF.getHeader().e_flags & ELF::EF_AMDGPU_MACH; - if (MACH >= ELF::EF_AMDGPU_MACH_R600_FIRST && - MACH <= ELF::EF_AMDGPU_MACH_R600_LAST) - return Triple::r600; - if (MACH >= ELF::EF_AMDGPU_MACH_AMDGCN_FIRST && - MACH <= ELF::EF_AMDGPU_MACH_AMDGCN_LAST) - return Triple::amdgcn; - - return Triple::UnknownArch; - } - - case ELF::EM_BPF: - return IsLittleEndian ? Triple::bpfel : Triple::bpfeb; - - case ELF::EM_VE: - return Triple::ve; + if (MACH >= ELF::EF_AMDGPU_MACH_R600_FIRST && + MACH <= ELF::EF_AMDGPU_MACH_R600_LAST) + return Triple::r600; + if (MACH >= ELF::EF_AMDGPU_MACH_AMDGCN_FIRST && + MACH <= ELF::EF_AMDGPU_MACH_AMDGCN_LAST) + return Triple::amdgcn; + + return Triple::UnknownArch; + } + + case ELF::EM_BPF: + return IsLittleEndian ? Triple::bpfel : Triple::bpfeb; + + case ELF::EM_VE: + return Triple::ve; case ELF::EM_CSKY: return Triple::csky; - default: - return Triple::UnknownArch; - } -} - -template <class ELFT> -Expected<uint64_t> ELFObjectFile<ELFT>::getStartAddress() const { + default: + return Triple::UnknownArch; + } +} + +template <class ELFT> +Expected<uint64_t> ELFObjectFile<ELFT>::getStartAddress() const { return EF.getHeader().e_entry; -} - -template <class ELFT> -ELFObjectFileBase::elf_symbol_iterator_range -ELFObjectFile<ELFT>::getDynamicSymbolIterators() const { - return make_range(dynamic_symbol_begin(), dynamic_symbol_end()); -} - -template <class ELFT> bool ELFObjectFile<ELFT>::isRelocatableObject() const { +} + +template <class ELFT> +ELFObjectFileBase::elf_symbol_iterator_range +ELFObjectFile<ELFT>::getDynamicSymbolIterators() const { + return make_range(dynamic_symbol_begin(), dynamic_symbol_end()); +} + +template <class ELFT> bool ELFObjectFile<ELFT>::isRelocatableObject() const { return EF.getHeader().e_type == ELF::ET_REL; -} - -} // end namespace object -} // end namespace llvm - -#endif // LLVM_OBJECT_ELFOBJECTFILE_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +} + +} // end namespace object +} // end namespace llvm + +#endif // LLVM_OBJECT_ELFOBJECTFILE_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif |
