fxos/include/fxos/binary.h

232 lines
6.3 KiB
C++

//---------------------------------------------------------------------------//
// 1100101 |_ mov #0, r4 __ //
// 11 |_ <0xb380 %5c4> / _|_ _____ ___ //
// 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< //
// |_ base# + offset |_| /_\_\___/__/ //
//---------------------------------------------------------------------------//
// fxos/binary: Main object for working with programs
//
// This header defines the main structures that combine to form the Binary
// object, which is the main access point for analyzing a program. The Binary
// structure references a VirtualSpace which emulates memory and can be used to
// read raw data. It then lists every Variable and Function that has been
// marked out in the program, either manually or by an analysis.
//---
#ifndef FXOS_BINARY_H
#define FXOS_BINARY_H
#include <fxos/util/types.h>
#include <fxos/util/bson.h>
#include <fxos/vspace.h>
#include <cassert>
#include <string>
#include <map>
namespace FxOS {
class OS;
struct BinaryObject;
struct Mark;
struct Variable;
struct Function;
struct Binary
{
/* Empty binary with an empty virtual space. */
Binary() = default;
BSON serialize() const;
void deserialize(BSON const &);
VirtualSpace &vspace()
{
return m_vspace;
}
VirtualSpace const &vspace() const
{
return m_vspace;
}
/* OS analysis (performed on-demand). Returns the new or cached OS
analysis results, nullptr if analysis failed. */
OS *OSAnalysis(bool force = false);
// TODO: Platform information in a binary
// TODO: Implement OS analysis
// TODO: Add and manage objects
std::multimap<u32, std::unique_ptr<BinaryObject>> const &objects() const
{
return m_objects;
}
/* Return the address of an object by name, if it exists. If there are
multiple objects with the same name, returns an arbitrary one. */
std::optional<u32> objectAddress(std::string const &name) const;
/* Return the address of an object defined at the specified address if
there is one, nullptr otherwise. If multiple objects are defined at the
specified address, an arbitrary one is returned. */
BinaryObject *objectAt(u32 address);
BinaryObject const *objectAt(u32 address) const;
/* Returns the list of all objects defined at the specified address. */
std::vector<BinaryObject *> objectsAt(u32 address);
std::vector<BinaryObject const *> objectsAt(u32 address) const;
/* Locate all objects that intersect an address. */
std::vector<BinaryObject *> objectsCovering(u32 address);
std::vector<BinaryObject const *> objectsCovering(u32 address) const;
private:
VirtualSpace m_vspace;
/* OS analysis results */
std::unique_ptr<OS> m_os;
/* All binary objects */
std::multimap<u32, std::unique_ptr<BinaryObject>> m_objects;
};
/* Base structure for all /binary objets/, ie. program objects that can be
declared in the program space. */
struct BinaryObject
{
enum Type : u8 { Mark, Variable, Function };
BinaryObject(Binary &binary, Type type, u32 address, u32 size):
m_binary {binary}, m_address {address}, m_size {size}, m_type {type}
{
}
/* Location and size in the address space. */
u32 address() const
{
return m_address;
}
u32 size() const
{
return m_size;
}
void setSize(u32 size)
{
m_size = size;
}
/* Binary that owns the object. */
Binary &parentBinary()
{
return m_binary;
}
Binary const &parentBinary() const
{
return m_binary;
}
/* Symbol name, no requirements on uniqueness or character set. */
std::string const &name() const
{
return m_name;
}
void setName(std::string const &name)
{
m_name = name;
}
/* User comment. */
std::string const &comment() const
{
return m_comment;
}
void setComment(std::string const &comment)
{
m_comment = comment;
}
/* Check for a non-empty intersection between two objects. */
bool intersects(BinaryObject const &other) const;
/* Check whether this object contains another object. */
bool contains(BinaryObject const &other) const;
/* User-readable string representation: "object <name> at <addr>" */
std::string str() const;
// TODO: BinaryObject serialization
/* Polymorphic accessors */
bool isMark() const
{
return m_type == Type::Mark;
}
bool isVariable() const
{
return m_type == Type::Variable;
}
bool isFunction() const
{
return m_type == Type::Function;
}
FxOS::Mark &getMark() const
{
assert(isMark() && "wrong BinaryObject accessor: not a Mark");
return *(FxOS::Mark *)this;
}
FxOS::Variable &getVariable() const
{
assert(isVariable() && "wrong BinaryObject accessor: not a Variable");
return *(FxOS::Variable *)this;
}
FxOS::Function &getFunction() const
{
assert(isFunction() && "wrong BinaryObject accessor: not a Function");
return *(FxOS::Function *)this;
}
private:
Binary &m_binary;
u32 m_address;
u32 m_size;
Type const m_type;
std::string m_name;
/* TODO: BinaryObject: don't reserve 32 bytes for empty comments */
std::string m_comment;
};
/* Basic, unattributed binary object used to mark out regions of code (eg.
"kernel", "timer driver", "LINK app", "zero", "interrupt handlers"...). May
alias with other binary objects. */
struct Mark: public BinaryObject
{
// TODO: Tags/colors in marks
// TODO: BinaryObject serialization
};
/* Binary object representing a non-empty piece of data. */
struct Variable: public BinaryObject
{
/* Create a new variable at the given location with the given name. The
type defaults to an unsigned machine word (u32). */
Variable(Binary &binary, u32 address, std::string const &name);
#if 0
DataType const *type() const
{
return m_type;
}
void setType(DataType const &type)
{
m_type = type;
BinaryObject::setSize(m_type.size());
}
private:
DataType const *m_type;
#endif
};
} /* namespace FxOS */
#endif /* FXOS_BINARY_H */