Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Improve abstraction layer
  * Enable bitness through ``LIEF::Header::is_32`` and
   ``LIEF::Header::is_64` (See #29)
  * Add ``modes`` ot the Python API
  * Abstract binary object type (executable, library...)
  • Loading branch information
romainthomas committed May 6, 2017
1 parent 957501f commit 78d1adb
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 16 deletions.
23 changes: 21 additions & 2 deletions api/python/Abstract/objects/pyHeader.cpp
Expand Up @@ -31,13 +31,32 @@ void init_LIEF_Header_class(py::module& m) {
.def_property("architecture",
static_cast<getter_t<LIEF::ARCHITECTURES>>(&LIEF::Header::architecture),
static_cast<setter_t<LIEF::ARCHITECTURES>>(&LIEF::Header::architecture),
"Target's architecture")
"Target architecture")

.def_property("modes",
static_cast<getter_t<const std::set<LIEF::MODES>&>>(&LIEF::Header::modes),
static_cast<setter_t<const std::set<LIEF::MODES>&>>(&LIEF::Header::modes),
"Target modes (32-bits, 64-bits...)")

.def_property("entrypoint",
static_cast<getter_t<uint64_t>>(&LIEF::Header::entrypoint),
static_cast<setter_t<uint64_t>>(&LIEF::Header::entrypoint),
"Binary's entrypoint")
"Binary entrypoint")

.def_property("object_type",
static_cast<getter_t<LIEF::OBJECT_TYPES>>(&LIEF::Header::object_type),
static_cast<setter_t<LIEF::OBJECT_TYPES>>(&LIEF::Header::object_type),
"Type of the binary (executable, library...)\n"
"See: " RST_CLASS_REF(lief.OBJECT_TYPES) "")


.def_property_readonly("is_32",
&LIEF::Header::is_32,
"``True`` if the binary target a ``32-bits`` architecture")

.def_property_readonly("is_64",
&LIEF::Header::is_64,
"``True`` if the binary target a ``64-bits`` architecture")


.def("__str__",
Expand Down
6 changes: 6 additions & 0 deletions include/LIEF/Abstract/Header.hpp
Expand Up @@ -39,6 +39,12 @@ class DLL_PUBLIC Header : public Visitable {
OBJECT_TYPES object_type(void) const;
uint64_t entrypoint(void) const;

//! @brief ``true`` if the binary target a ``32-bits`` architecture
bool is_32(void) const;

//! @brief ``true`` if the binary target a ``64-bits`` architecture
bool is_64(void) const;

//! @brief Method so that the ``visitor`` can visit us
virtual void accept(Visitor& visitor) const override;

Expand Down
2 changes: 1 addition & 1 deletion include/LIEF/ELF/Header.hpp
Expand Up @@ -47,7 +47,7 @@ class DLL_PUBLIC Header : public Visitable {
//! @brief Define the object file type. (e.g. executable, library...)
E_TYPE file_type(void) const;

// @brief LIEF abstract object type
//! @brief LIEF abstract object type
OBJECT_TYPES abstract_object_type(void) const;

//! @brief Target architecture
Expand Down
3 changes: 3 additions & 0 deletions include/LIEF/MachO/Header.hpp
Expand Up @@ -50,6 +50,9 @@ class DLL_PUBLIC Header : public Visitable {
uint32_t flags(void) const;
uint32_t reserved(void) const;

//! @brief LIEF abstract object type
OBJECT_TYPES abstract_object_type(void) const;

std::pair<ARCHITECTURES, std::set<MODES>> abstract_architecture(void) const;

void magic(uint32_t magic);
Expand Down
23 changes: 22 additions & 1 deletion src/Abstract/Header.cpp
Expand Up @@ -48,6 +48,16 @@ const std::set<MODES>& Header::modes(void) const {
}


bool Header::is_32(void) const {
return this->modes().count(MODES::MODE_32) > 0;
}


bool Header::is_64(void) const {
return this->modes().count(MODES::MODE_64) > 0;
}


uint64_t Header::entrypoint(void) const {
return this->entrypoint_;
}
Expand Down Expand Up @@ -87,8 +97,19 @@ std::ostream& operator<<(std::ostream& os, const Header& hdr) {
});
os << std::hex << std::left;

std::string bitness = "UNKNOWN";
if (hdr.is_32()) {
bitness = "32";
}

if (hdr.is_64()) {
bitness = "64";
}

os << std::setw(33) << std::setfill(' ') << "Architecture:" << to_string(hdr.architecture()) << "_" << modes << std::endl;
os << std::setw(33) << std::setfill(' ') << "Entrypoint:" << "0x" << hdr.entrypoint() << std::endl;
os << std::setw(33) << std::setfill(' ') << "Entrypoint:" << "0x" << hdr.entrypoint() << std::endl;
os << std::setw(33) << std::setfill(' ') << "Object type:" << to_string(hdr.object_type()) << std::endl;
os << std::setw(33) << std::setfill(' ') << "32/64 bits:" << bitness << std::endl;
return os;
}

Expand Down
6 changes: 3 additions & 3 deletions src/ELF/Header.cpp
Expand Up @@ -28,10 +28,10 @@ namespace LIEF {
namespace ELF {

static const std::map<ARCH, std::pair<ARCHITECTURES, std::set<MODES>>> arch_elf_to_lief {
{ARCH::EM_NONE, {ARCH_NONE, {}}},
{ARCH::EM_NONE, {ARCH_NONE, {}}},
{ARCH::EM_X86_64, {ARCH_X86, {MODE_64}}},
{ARCH::EM_ARM, {ARCH_ARM, {}}},
{ARCH::EM_AARCH64, {ARCH_ARM64, {}}},
{ARCH::EM_ARM, {ARCH_ARM, {MODE_32}}},
{ARCH::EM_AARCH64, {ARCH_ARM64, {MODE_64}}},
{ARCH::EM_386, {ARCH_X86, {MODE_32}}},
{ARCH::EM_IA_64, {ARCH_INTEL, {MODE_64}}},
};
Expand Down
2 changes: 2 additions & 0 deletions src/MachO/Binary.cpp
Expand Up @@ -490,6 +490,8 @@ LIEF::Header Binary::get_abstract_header(void) const {
header.entrypoint(0);
}

header.object_type(this->header().abstract_object_type());

return header;
}

Expand Down
23 changes: 19 additions & 4 deletions src/MachO/Header.cpp
Expand Up @@ -32,14 +32,20 @@ namespace LIEF {
namespace MachO {

static const std::map<CPU_TYPES, std::pair<ARCHITECTURES, std::set<MODES>>> arch_macho_to_lief {
{CPU_TYPES::CPU_TYPE_ANY, {ARCH_NONE, {}}},
{CPU_TYPES::CPU_TYPE_ANY, {ARCH_NONE, {}}},
{CPU_TYPES::CPU_TYPE_X86_64, {ARCH_X86, {MODE_64}}},
{CPU_TYPES::CPU_TYPE_ARM, {ARCH_ARM, {}}},
{CPU_TYPES::CPU_TYPE_ARM64, {ARCH_ARM64, {}}},
{CPU_TYPES::CPU_TYPE_ARM, {ARCH_ARM, {MODE_32}}},
{CPU_TYPES::CPU_TYPE_ARM64, {ARCH_ARM64, {MODE_64}}},
{CPU_TYPES::CPU_TYPE_X86, {ARCH_X86, {MODE_32}}},
{CPU_TYPES::CPU_TYPE_SPARC, {ARCH_SPARC, {}}},
{CPU_TYPES::CPU_TYPE_POWERPC, {ARCH_PPC, {MODE_32}}},
{CPU_TYPES::CPU_TYPE_POWERPC64, {ARCH_PPC, {MODE_64}}},
{CPU_TYPES::CPU_TYPE_POWERPC64, {ARCH_PPC, {MODE_64}}},
};

static const std::map<FILE_TYPES, OBJECT_TYPES> obj_macho_to_lief {
{FILE_TYPES::MH_EXECUTE, OBJECT_TYPES::TYPE_EXECUTABLE},
{FILE_TYPES::MH_DYLIB, OBJECT_TYPES::TYPE_LIBRARY},
{FILE_TYPES::MH_OBJECT, OBJECT_TYPES::TYPE_OBJECT},
};

Header::Header(void) = default;
Expand Down Expand Up @@ -109,6 +115,15 @@ std::pair<ARCHITECTURES, std::set<MODES>> Header::abstract_architecture(void) co
}
}


OBJECT_TYPES Header::abstract_object_type(void) const {
try {
return obj_macho_to_lief.at(this->file_type());
} catch (const std::out_of_range&) {
throw not_implemented(to_string(this->file_type()));
}
}

std::set<HEADER_FLAGS> Header::flags_list(void) const {
std::set<HEADER_FLAGS> flags;

Expand Down
19 changes: 14 additions & 5 deletions src/PE/Binary.cpp
Expand Up @@ -35,14 +35,14 @@ namespace LIEF {
namespace PE {

static const std::map<MACHINE_TYPES, std::pair<ARCHITECTURES, std::set<MODES>>> arch_pe_to_lief {
{MACHINE_TYPES::IMAGE_FILE_MACHINE_UNKNOWN, {ARCH_NONE, {}}},
{MACHINE_TYPES::IMAGE_FILE_MACHINE_UNKNOWN, {ARCH_NONE, {}}},
{MACHINE_TYPES::IMAGE_FILE_MACHINE_AMD64, {ARCH_X86, {MODE_64}}},
{MACHINE_TYPES::IMAGE_FILE_MACHINE_ARM, {ARCH_ARM, {MODE_LITTLE_ENDIAN}}},
{MACHINE_TYPES::IMAGE_FILE_MACHINE_ARMNT, {ARCH_ARM, {MODE_V7, MODE_THUMB}}},
{MACHINE_TYPES::IMAGE_FILE_MACHINE_ARM64, {ARCH_ARM64, {MODE_V8}}},
{MACHINE_TYPES::IMAGE_FILE_MACHINE_ARM, {ARCH_ARM, {MODE_32, MODE_LITTLE_ENDIAN}}},
{MACHINE_TYPES::IMAGE_FILE_MACHINE_ARMNT, {ARCH_ARM, {MODE_32, MODE_V7, MODE_THUMB}}},
{MACHINE_TYPES::IMAGE_FILE_MACHINE_ARM64, {ARCH_ARM64, {MODE_64, MODE_V8}}},
{MACHINE_TYPES::IMAGE_FILE_MACHINE_I386, {ARCH_X86, {MODE_32}}},
{MACHINE_TYPES::IMAGE_FILE_MACHINE_IA64, {ARCH_INTEL, {MODE_64}}},
{MACHINE_TYPES::IMAGE_FILE_MACHINE_THUMB, {ARCH_ARM, {MODE_THUMB}}},
{MACHINE_TYPES::IMAGE_FILE_MACHINE_THUMB, {ARCH_ARM, {MODE_32, MODE_THUMB}}},
};

Binary::Binary(void) :
Expand Down Expand Up @@ -911,6 +911,15 @@ LIEF::Header Binary::get_abstract_header(void) const {

header.entrypoint(this->entrypoint());

if (this->header().has_characteristic(HEADER_CHARACTERISTICS::IMAGE_FILE_DLL)) {
header.object_type(OBJECT_TYPES::TYPE_LIBRARY);
} else if (this->header().has_characteristic(HEADER_CHARACTERISTICS::IMAGE_FILE_EXECUTABLE_IMAGE)) {
header.object_type(OBJECT_TYPES::TYPE_EXECUTABLE);
} else {
header.object_type(OBJECT_TYPES::TYPE_NONE);
}


return header;
}

Expand Down

0 comments on commit 78d1adb

Please sign in to comment.