Move header files to dwarfinterpret/
This commit is contained in:
parent
3c9dae009e
commit
d893b9138a
3 changed files with 149 additions and 145 deletions
|
@ -1,147 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <cstdint>
|
||||
|
||||
#include <dwarfpp/lib.hpp>
|
||||
#include <dwarfpp/regs.hpp>
|
||||
#include <dwarfpp/frame.hpp>
|
||||
#include <dwarfpp/attr.hpp>
|
||||
#include <dwarfpp/frame.hpp>
|
||||
#include <dwarfpp/root.hpp>
|
||||
|
||||
#define OF_WHAT_EXCEPTION(cl_name) \
|
||||
cl_name: public WhatException { \
|
||||
public:\
|
||||
cl_name(const std::string& what): WhatException(what) {} \
|
||||
cl_name() = default; \
|
||||
}
|
||||
|
||||
class DwarfInterpret {
|
||||
/** Singleton class holding a Dwarf interpret.
|
||||
* Must be first instanciated with the path to the binary being run, with a
|
||||
* call to `instanciate`, and can afterwards be accessed with calls to
|
||||
* `acquire`.
|
||||
*/
|
||||
|
||||
public: // Types, sub-classes, …
|
||||
class WhatException: public std::exception {
|
||||
/** Base exception for other exceptions, not supposed to be thrown
|
||||
* by itself */
|
||||
|
||||
std::string what_str;
|
||||
|
||||
public:
|
||||
/// Initialize the exception with an explanatory text chunk
|
||||
explicit WhatException(const std::string& what)
|
||||
: what_str(what) {}
|
||||
|
||||
/// Leave the explanatory text empty
|
||||
WhatException(): what_str("") {}
|
||||
|
||||
/// Get the explanatory text for this exception
|
||||
const char* what() const noexcept {
|
||||
return what_str.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Thrown when `acquire` is called before `instanciate`
|
||||
class OF_WHAT_EXCEPTION(NotInstanciated);
|
||||
|
||||
/// Thrown when `instanciate` is called twice
|
||||
class OF_WHAT_EXCEPTION(AlreadyInstanciated);
|
||||
|
||||
/** Thrown when trying to get the value of a Dwarf register (column)
|
||||
* that is not defined or has, somehow, no value at this PC. */
|
||||
class OF_WHAT_EXCEPTION(ValuelessRegister);
|
||||
|
||||
/// Thrown when accessing unimplemented parts of this library
|
||||
class OF_WHAT_EXCEPTION(NotImplemented);
|
||||
|
||||
/// Thrown when somehow, getcontext (read CPU registers) fails
|
||||
class OF_WHAT_EXCEPTION(FailedGetContext);
|
||||
|
||||
/// Thrown when a Dwarf element is not found for a given PC
|
||||
class OF_WHAT_EXCEPTION(NotFound);
|
||||
|
||||
|
||||
/// A Dwarf register
|
||||
typedef dwarf::core::FrameSection::register_def DwarfRegister;
|
||||
|
||||
/// A Dwarf row of registers (for a given PC)
|
||||
typedef std::set<std::pair<int, DwarfRegister> > DwarfRow;
|
||||
|
||||
/// The value type of a register's contents
|
||||
typedef uintptr_t reg_content_t;
|
||||
|
||||
public: // methods
|
||||
DwarfInterpret(DwarfInterpret const&) = delete;
|
||||
void operator=(DwarfInterpret const&) = delete;
|
||||
|
||||
/** Acquire the instance of `DwarfInterpret`. The method #instanciate
|
||||
* must have been called beforehand.
|
||||
*
|
||||
* \throws NotInstanciated whenever this condition is not met.
|
||||
*/
|
||||
static DwarfInterpret& acquire();
|
||||
|
||||
/** Instanciate the instance of DwarfInterpret with the path to the
|
||||
* program currently running (usually, argv[0])
|
||||
*
|
||||
* \throws AlreadyInstanciated if this method is called twice. */
|
||||
static DwarfInterpret& instanciate(const std::string& elf_path);
|
||||
|
||||
/// Returns the ELF machine number for this ELF
|
||||
int get_elf_machine() const { return elf_machine; }
|
||||
|
||||
/** Retrieves the value pointed to by the given Dwarf register
|
||||
*
|
||||
* \throws ValuelessRegister */
|
||||
reg_content_t interpret_dw_register(
|
||||
const DwarfRow& row,
|
||||
const DwarfRegister& reg
|
||||
) const;
|
||||
|
||||
/** Retrieves the value pointed to by the given Dwarf register
|
||||
*
|
||||
* \throws ValuelessRegister */
|
||||
reg_content_t interpret_dw_register(
|
||||
const DwarfRow& row,
|
||||
int reg_id
|
||||
) const;
|
||||
|
||||
/** Get the return address at a given program counter, assuming the
|
||||
* correct registers are stored */
|
||||
uintptr_t get_return_address(uintptr_t cur_pc) const;
|
||||
|
||||
/** Get the return address of the current program point */
|
||||
uintptr_t get_self_return_address() const;
|
||||
|
||||
/// Get the current program counter
|
||||
static uintptr_t get_current_pc();
|
||||
|
||||
private:
|
||||
DwarfInterpret(const std::string& elf_path);
|
||||
|
||||
DwarfRegister get_column(const DwarfRow& row, int column) const;
|
||||
reg_content_t get_cpu_register(int reg_id) const;
|
||||
|
||||
const dwarf::core::FrameSection::fde_iterator fde_at(
|
||||
uintptr_t pc) const;
|
||||
const dwarf::core::FrameSection::cie_iterator cie_at(
|
||||
uintptr_t pc) const;
|
||||
const DwarfRow& dwarf_row_at(uintptr_t pc) const;
|
||||
|
||||
uintptr_t get_caller_pc() const;
|
||||
|
||||
|
||||
private: // members
|
||||
static std::unique_ptr<DwarfInterpret> instance;
|
||||
|
||||
dwarf::core::root_die root_die;
|
||||
int elf_machine;
|
||||
|
||||
friend class std::unique_ptr<DwarfInterpret>;
|
||||
};
|
||||
#include <dwarfinterpret/DwarfInterpret.hpp>
|
||||
#include <dwarfinterpret/MemoryMap.hpp>
|
||||
|
|
147
include/dwarfinterpret/DwarfInterpret.hpp
Normal file
147
include/dwarfinterpret/DwarfInterpret.hpp
Normal file
|
@ -0,0 +1,147 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <cstdint>
|
||||
|
||||
#include <dwarfpp/lib.hpp>
|
||||
#include <dwarfpp/regs.hpp>
|
||||
#include <dwarfpp/frame.hpp>
|
||||
#include <dwarfpp/attr.hpp>
|
||||
#include <dwarfpp/frame.hpp>
|
||||
#include <dwarfpp/root.hpp>
|
||||
|
||||
#define OF_WHAT_EXCEPTION(cl_name) \
|
||||
cl_name: public WhatException { \
|
||||
public:\
|
||||
cl_name(const std::string& what): WhatException(what) {} \
|
||||
cl_name() = default; \
|
||||
}
|
||||
|
||||
class DwarfInterpret {
|
||||
/** Singleton class holding a Dwarf interpret.
|
||||
* Must be first instanciated with the path to the binary being run, with a
|
||||
* call to `instanciate`, and can afterwards be accessed with calls to
|
||||
* `acquire`.
|
||||
*/
|
||||
|
||||
public: // Types, sub-classes, …
|
||||
class WhatException: public std::exception {
|
||||
/** Base exception for other exceptions, not supposed to be thrown
|
||||
* by itself */
|
||||
|
||||
std::string what_str;
|
||||
|
||||
public:
|
||||
/// Initialize the exception with an explanatory text chunk
|
||||
explicit WhatException(const std::string& what)
|
||||
: what_str(what) {}
|
||||
|
||||
/// Leave the explanatory text empty
|
||||
WhatException(): what_str("") {}
|
||||
|
||||
/// Get the explanatory text for this exception
|
||||
const char* what() const noexcept {
|
||||
return what_str.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Thrown when `acquire` is called before `instanciate`
|
||||
class OF_WHAT_EXCEPTION(NotInstanciated);
|
||||
|
||||
/// Thrown when `instanciate` is called twice
|
||||
class OF_WHAT_EXCEPTION(AlreadyInstanciated);
|
||||
|
||||
/** Thrown when trying to get the value of a Dwarf register (column)
|
||||
* that is not defined or has, somehow, no value at this PC. */
|
||||
class OF_WHAT_EXCEPTION(ValuelessRegister);
|
||||
|
||||
/// Thrown when accessing unimplemented parts of this library
|
||||
class OF_WHAT_EXCEPTION(NotImplemented);
|
||||
|
||||
/// Thrown when somehow, getcontext (read CPU registers) fails
|
||||
class OF_WHAT_EXCEPTION(FailedGetContext);
|
||||
|
||||
/// Thrown when a Dwarf element is not found for a given PC
|
||||
class OF_WHAT_EXCEPTION(NotFound);
|
||||
|
||||
|
||||
/// A Dwarf register
|
||||
typedef dwarf::core::FrameSection::register_def DwarfRegister;
|
||||
|
||||
/// A Dwarf row of registers (for a given PC)
|
||||
typedef std::set<std::pair<int, DwarfRegister> > DwarfRow;
|
||||
|
||||
/// The value type of a register's contents
|
||||
typedef uintptr_t reg_content_t;
|
||||
|
||||
public: // methods
|
||||
DwarfInterpret(DwarfInterpret const&) = delete;
|
||||
void operator=(DwarfInterpret const&) = delete;
|
||||
|
||||
/** Acquire the instance of `DwarfInterpret`. The method #instanciate
|
||||
* must have been called beforehand.
|
||||
*
|
||||
* \throws NotInstanciated whenever this condition is not met.
|
||||
*/
|
||||
static DwarfInterpret& acquire();
|
||||
|
||||
/** Instanciate the instance of DwarfInterpret with the path to the
|
||||
* program currently running (usually, argv[0])
|
||||
*
|
||||
* \throws AlreadyInstanciated if this method is called twice. */
|
||||
static DwarfInterpret& instanciate(const std::string& elf_path);
|
||||
|
||||
/// Returns the ELF machine number for this ELF
|
||||
int get_elf_machine() const { return elf_machine; }
|
||||
|
||||
/** Retrieves the value pointed to by the given Dwarf register
|
||||
*
|
||||
* \throws ValuelessRegister */
|
||||
reg_content_t interpret_dw_register(
|
||||
const DwarfRow& row,
|
||||
const DwarfRegister& reg
|
||||
) const;
|
||||
|
||||
/** Retrieves the value pointed to by the given Dwarf register
|
||||
*
|
||||
* \throws ValuelessRegister */
|
||||
reg_content_t interpret_dw_register(
|
||||
const DwarfRow& row,
|
||||
int reg_id
|
||||
) const;
|
||||
|
||||
/** Get the return address at a given program counter, assuming the
|
||||
* correct registers are stored */
|
||||
uintptr_t get_return_address(uintptr_t cur_pc) const;
|
||||
|
||||
/** Get the return address of the current program point */
|
||||
uintptr_t get_self_return_address() const;
|
||||
|
||||
/// Get the current program counter
|
||||
static uintptr_t get_current_pc();
|
||||
|
||||
private:
|
||||
DwarfInterpret(const std::string& elf_path);
|
||||
|
||||
DwarfRegister get_column(const DwarfRow& row, int column) const;
|
||||
reg_content_t get_cpu_register(int reg_id) const;
|
||||
|
||||
const dwarf::core::FrameSection::fde_iterator fde_at(
|
||||
uintptr_t pc) const;
|
||||
const dwarf::core::FrameSection::cie_iterator cie_at(
|
||||
uintptr_t pc) const;
|
||||
const DwarfRow& dwarf_row_at(uintptr_t pc) const;
|
||||
|
||||
uintptr_t get_caller_pc() const;
|
||||
|
||||
|
||||
private: // members
|
||||
static std::unique_ptr<DwarfInterpret> instance;
|
||||
|
||||
dwarf::core::root_die root_die;
|
||||
int elf_machine;
|
||||
|
||||
friend class std::unique_ptr<DwarfInterpret>;
|
||||
};
|
Loading…
Reference in a new issue