#ifndef _BINARYFILE_H #define _BINARYFILE_H // // This file is distributed under the MIT License. See LICENSE.md for details. // // Standard includes #include #include // LLVM includes #include "llvm/Object/Binary.h" // Local includes #include "revamb.h" namespace llvm { namespace object { class ObjectFile; } } /// \brief Simple data structure to describe an ELF segment // TODO: information hiding struct SegmentInfo { /// Produce a name for this segment suitable for human understanding std::string generateName(); llvm::GlobalVariable *Variable; ///< \brief LLVM variable containing this /// segment's data uint64_t StartVirtualAddress; uint64_t EndVirtualAddress; bool IsWriteable; bool IsExecutable; bool IsReadable; std::vector> ExecutableSections; llvm::ArrayRef Data; bool contains(uint64_t Address) const { return StartVirtualAddress <= Address && Address < EndVirtualAddress; } bool contains(uint64_t Start, uint64_t Size) const { return contains(Start) && contains(Start + Size - 1); } uint64_t size() const { return EndVirtualAddress - StartVirtualAddress; } template void insertExecutableRanges(std::back_insert_iterator Inserter) const { if (!IsExecutable) return; if (ExecutableSections.size() > 0) { std::copy(ExecutableSections.begin(), ExecutableSections.end(), Inserter); } else { Inserter = std::make_pair(StartVirtualAddress, EndVirtualAddress); } } }; /// \brief Simple data structure to describe a symbol in an image format /// independent way // TODO: information hiding struct SymbolInfo { llvm::StringRef Name; uint64_t Address; uint64_t Size; bool operator<(const SymbolInfo &Other) const { return Address < Other.Address; } bool operator==(const SymbolInfo &Other) const { return Name == Other.Name && Address == Other.Address && Size == Other.Size; } }; /// \brief BinaryFile describes an input image file in a semi-architecture /// independent way class BinaryFile { public: /// \param FilePath the path to the input file. /// \param UseSections whether information in sections, if available, should /// be employed or not. This is useful to precisely identify exeutable /// code. BinaryFile(std::string FilePath, bool UseSections); // Accessors const Architecture &architecture() const { return TheArchitecture; } std::vector &segments() { return Segments; } const std::vector &segments() const { return Segments; } const std::vector &symbols() const { return Symbols; } uint64_t entryPoint() const { return EntryPoint; } // ELF specific accessors uint64_t programHeadersAddress() const { return ProgramHeaders.Address; } unsigned programHeaderSize() const { return ProgramHeaders.Size; } unsigned programHeadersCount() const { return ProgramHeaders.Count; } private: template void parseELF(llvm::object::ObjectFile *TheBinary, bool UseSections); private: llvm::object::OwningBinary BinaryHandle; Architecture TheArchitecture; std::vector Symbols; std::vector Segments; uint64_t EntryPoint; // ELF specific fields struct { uint64_t Address; unsigned Count; unsigned Size; } ProgramHeaders; }; #endif // _BINARYFILE_H