mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
832840c307
This commit ensures that parts of the model that must point to code (specifically `Binary::EntryPoint`, `Binary::ExtraCodeAddresses` and `Function::Entry`) actually point to a segment mapped as +x.
178 lines
5.3 KiB
C++
178 lines
5.3 KiB
C++
#pragma once
|
|
|
|
//
|
|
// This file is distributed under the MIT License. See LICENSE.md for details.
|
|
//
|
|
|
|
#include "llvm/Object/ELFObjectFile.h"
|
|
|
|
#include "revng/Model/Importer/Binary/BinaryImporterHelper.h"
|
|
#include "revng/Model/Importer/Binary/Options.h"
|
|
#include "revng/Model/RawBinaryView.h"
|
|
#include "revng/Support/MetaAddress.h"
|
|
|
|
#include "DwarfReader.h"
|
|
#include "SegmentImportHelpers.h"
|
|
|
|
extern Logger<> ELFImporterLog;
|
|
|
|
namespace {
|
|
|
|
class FilePortion {
|
|
private:
|
|
const RawBinaryView &File;
|
|
bool HasAddress;
|
|
bool HasSize;
|
|
uint64_t Size;
|
|
MetaAddress Address;
|
|
|
|
public:
|
|
FilePortion(const RawBinaryView &File);
|
|
|
|
public:
|
|
MetaAddress address() const { return Address; }
|
|
uint64_t size() const { return Size; }
|
|
|
|
public:
|
|
void setAddress(MetaAddress Address);
|
|
void setSize(uint64_t Size);
|
|
|
|
MetaAddress addressAtOffset(uint64_t Offset);
|
|
|
|
template<typename T>
|
|
MetaAddress addressAtIndex(uint64_t Index);
|
|
|
|
bool isAvailable() const;
|
|
bool isExact() const;
|
|
|
|
llvm::StringRef extractString() const;
|
|
|
|
template<typename T>
|
|
llvm::ArrayRef<T> extractAs() const;
|
|
llvm::ArrayRef<uint8_t> extractData() const;
|
|
};
|
|
|
|
class ELFImporterBase {
|
|
public:
|
|
virtual ~ELFImporterBase() = default;
|
|
virtual llvm::Error import(const ImporterOptions &Options) = 0;
|
|
};
|
|
|
|
template<typename T, bool HasAddend>
|
|
class ELFImporter : public BinaryImporterHelper, public ELFImporterBase {
|
|
private:
|
|
RawBinaryView File;
|
|
TupleTree<model::Binary> &Model;
|
|
const llvm::object::ELFObjectFileBase &TheBinary;
|
|
|
|
std::optional<MetaAddress> EHFrameHdrAddress;
|
|
std::optional<MetaAddress> DynamicAddress;
|
|
|
|
llvm::SmallVector<DataSymbol, 32> DataSymbols;
|
|
|
|
protected:
|
|
std::optional<uint64_t> SymbolsCount;
|
|
std::unique_ptr<FilePortion> DynstrPortion;
|
|
std::unique_ptr<FilePortion> DynsymPortion;
|
|
std::unique_ptr<FilePortion> ReldynPortion;
|
|
std::unique_ptr<FilePortion> RelpltPortion;
|
|
std::unique_ptr<FilePortion> GotPortion;
|
|
|
|
public:
|
|
ELFImporter(TupleTree<model::Binary> &Model,
|
|
const llvm::object::ELFObjectFileBase &TheBinary,
|
|
uint64_t BaseAddress) :
|
|
BinaryImporterHelper(*Model, BaseAddress, ELFImporterLog),
|
|
File(*Model, toArrayRef(TheBinary.getData())),
|
|
Model(Model),
|
|
TheBinary(TheBinary) {}
|
|
|
|
private:
|
|
using Elf_Rel = llvm::object::Elf_Rel_Impl<T, HasAddend>;
|
|
using Elf_Rel_Array = llvm::ArrayRef<Elf_Rel>;
|
|
using ConstElf_Shdr = const typename llvm::object::ELFFile<T>::Elf_Shdr;
|
|
|
|
public:
|
|
llvm::Error import(const ImporterOptions &Options) override;
|
|
|
|
private:
|
|
MetaAddress getGenericPointer(Pointer Ptr) const {
|
|
if (not Ptr.isIndirect())
|
|
return Ptr.value();
|
|
|
|
auto MaybePointer = File.getFromAddressOn(Ptr.value());
|
|
if (not MaybePointer)
|
|
return MetaAddress::invalid();
|
|
|
|
return fromGeneric(::readPointer<T>(MaybePointer->data()));
|
|
}
|
|
|
|
MetaAddress getCodePointer(Pointer Ptr) const {
|
|
using namespace model::Architecture;
|
|
auto Architecture = Model->Architecture();
|
|
return this->getGenericPointer(Ptr).toPC(toLLVMArchitecture(Architecture));
|
|
}
|
|
|
|
/// Parse the .eh_frame_hdr section to obtain the address and the number of
|
|
/// FDEs in .eh_frame
|
|
///
|
|
/// \return a pair containing a (possibly invalid) pointer to the .eh_frame
|
|
/// section and the count of FDEs in the .eh_frame_hdr section (which
|
|
/// should match the number of FDEs in .eh_frame)
|
|
std::pair<MetaAddress, uint64_t> ehFrameFromEhFrameHdr();
|
|
|
|
/// Parse the .eh_frame section to collect all the landing pads
|
|
///
|
|
/// \param EHFrameAddress the address of the .eh_frame section
|
|
/// \param FDEsCount the count of FDEs in the .eh_frame section
|
|
/// \param EHFrameSize the size of the .eh_frame section
|
|
///
|
|
/// \note Either \p FDEsCount or \p EHFrameSize have to be specified
|
|
void parseEHFrame(MetaAddress EHFrameAddress,
|
|
std::optional<uint64_t> FDEsCount,
|
|
std::optional<uint64_t> EHFrameSize);
|
|
|
|
/// Parse an LSDA to collect its landing pads
|
|
///
|
|
/// \param FDEStart the start address of the FDE to which this LSDA is
|
|
/// associated
|
|
/// \param LSDAAddress the address of the target LSDA
|
|
void parseLSDA(MetaAddress FDEStart, MetaAddress LSDAAddress);
|
|
|
|
void parseSymbols(llvm::object::ELFFile<T> &TheELF,
|
|
ConstElf_Shdr *SectionHeader);
|
|
|
|
void parseSegments(llvm::object::ELFFile<T> &TheELF);
|
|
|
|
void parseProgramHeaders(llvm::object::ELFFile<T> &TheELF);
|
|
|
|
void parseDynamicSymbol(llvm::object::Elf_Sym_Impl<T> &Symbol,
|
|
llvm::StringRef Dynstr);
|
|
|
|
void findMissingTypes(llvm::object::ELFFile<T> &TheELF,
|
|
const ImporterOptions &Options);
|
|
|
|
protected:
|
|
template<typename Q>
|
|
using SmallVectorImpl = llvm::SmallVectorImpl<Q>;
|
|
|
|
/// Register a label for each input relocation
|
|
void registerRelocations(Elf_Rel_Array Relocations,
|
|
const FilePortion &Dynsym,
|
|
const FilePortion &Dynstr);
|
|
|
|
void parseDynamicTag(uint64_t Tag,
|
|
uint64_t Val,
|
|
uint64_t Pointer,
|
|
SmallVectorImpl<uint64_t> &LibrariesOffsets);
|
|
|
|
/// Parse architecture dynamic tags.
|
|
virtual void
|
|
parseTargetDynamicTags(uint64_t Tag,
|
|
MetaAddress Relocated,
|
|
SmallVectorImpl<uint64_t> &NeededLibraryNameOffsets,
|
|
uint64_t Val) {}
|
|
};
|
|
|
|
} // end anonymous namespace
|