Skip to content

Commit

Permalink
Show Mach-O opcodes and export-trie
Browse files Browse the repository at this point in the history
  • Loading branch information
romainthomas committed Mar 2, 2018
1 parent 135aeab commit 5d56141
Show file tree
Hide file tree
Showing 24 changed files with 1,104 additions and 23 deletions.
24 changes: 24 additions & 0 deletions api/python/MachO/objects/pyDyldInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ void init_MachO_DyldInfo_class(py::module& m) {
static_cast<setter_t<const buffer_t&>>(&DyldInfo::rebase_opcodes),
"Return Rebase's opcodes as ``list`` of bytes")

.def_property_readonly("show_rebases_opcodes",
&DyldInfo::show_rebases_opcodes,
"Return the rebase opcodes in a humman-readable way",
py::return_value_policy::reference_internal)

.def_property("bind",
static_cast<getter_t<const LIEF::MachO::DyldInfo::info_t&>>(&DyldInfo::bind),
static_cast<setter_t<const LIEF::MachO::DyldInfo::info_t&>>(&DyldInfo::bind),
Expand All @@ -86,6 +91,11 @@ void init_MachO_DyldInfo_class(py::module& m) {
static_cast<setter_t<const buffer_t&>>(&DyldInfo::bind_opcodes),
"Return Binding's opcodes as ``list`` of bytes")

.def_property_readonly("show_bind_opcodes",
&DyldInfo::show_bind_opcodes,
"Return the bind opcodes in a humman-readable way",
py::return_value_policy::reference_internal)


.def_property("weak_bind",
static_cast<getter_t<const LIEF::MachO::DyldInfo::info_t&>>(&DyldInfo::weak_bind),
Expand Down Expand Up @@ -116,6 +126,10 @@ void init_MachO_DyldInfo_class(py::module& m) {
static_cast<setter_t<const buffer_t&>>(&DyldInfo::weak_bind_opcodes),
"Return **Weak** binding's opcodes as ``list`` of bytes")

.def_property_readonly("show_weak_bind_opcodes",
&DyldInfo::show_weak_bind_opcodes,
"Return the weak bind opcodes in a humman-readable way",
py::return_value_policy::reference_internal)

.def_property("lazy_bind",
static_cast<getter_t<const LIEF::MachO::DyldInfo::info_t&>>(&DyldInfo::lazy_bind),
Expand Down Expand Up @@ -143,6 +157,11 @@ void init_MachO_DyldInfo_class(py::module& m) {
static_cast<setter_t<const buffer_t&>>(&DyldInfo::lazy_bind_opcodes),
"Return **lazy** binding's opcodes as ``list`` of bytes")

.def_property_readonly("show_lazy_bind_opcodes",
&DyldInfo::show_lazy_bind_opcodes,
"Return the weak bind opcodes in a humman-readable way",
py::return_value_policy::reference_internal)

.def_property_readonly("bindings",
static_cast<no_const_getter<it_binding_info>>(&DyldInfo::bindings),
"Return an iterator over Dyld's " RST_CLASS_REF(lief.MachO.BindingInfo) "",
Expand Down Expand Up @@ -190,6 +209,11 @@ void init_MachO_DyldInfo_class(py::module& m) {
"Return an iterator over Dyld's " RST_CLASS_REF(lief.MachO.ExportInfo) "",
py::return_value_policy::reference_internal)

.def_property_readonly("show_export_trie",
&DyldInfo::show_export_trie,
"Return the export trie in a humman-readable way",
py::return_value_policy::reference_internal)

.def("set_rebase_offset",
&DyldInfo::set_rebase_offset,
"offset"_a)
Expand Down
4 changes: 4 additions & 0 deletions api/python/MachO/objects/pySymbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ void init_MachO_Symbol_class(py::module& m) {
&Symbol::has_export_info,
"``True`` if the symbol has a " RST_CLASS_REF(lief.MachO.ExportInfo) " associated with")

.def_property_readonly("origin",
&Symbol::origin,
"Return the " RST_CLASS_REF(lief.MachO.SYMBOL_ORIGINS) " of this symbol")

.def_property_readonly("export_info",
static_cast<ExportInfo& (Symbol::*)(void)>(&Symbol::export_info),
"" RST_CLASS_REF(lief.MachO.ExportInfo) " associated with the symbol (if any)",
Expand Down
7 changes: 7 additions & 0 deletions api/python/MachO/pyMachOStructures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,13 @@ void init_MachO_Structures_enum(py::module& m) {
.export_values();


py::enum_<LIEF::MachO::SYMBOL_ORIGINS>(m, "SYMBOL_ORIGINS")
.value(PY_ENUM(LIEF::MachO::SYMBOL_ORIGINS::SYM_ORIGIN_UNKNOWN))
.value(PY_ENUM(LIEF::MachO::SYMBOL_ORIGINS::SYM_ORIGIN_DYLD_EXPORT))
.value(PY_ENUM(LIEF::MachO::SYMBOL_ORIGINS::SYM_ORIGIN_LC_SYMTAB))
.export_values();





Expand Down
3 changes: 3 additions & 0 deletions doc/sphinx/api/cpp/macho.rst
Original file line number Diff line number Diff line change
Expand Up @@ -327,3 +327,6 @@ Enums
.. doxygenenum:: LIEF::MachO::VM_PROTECTIONS
:project: lief

.. doxygenenum:: LIEF::MachO::SYMBOL_ORIGINS
:project: lief

11 changes: 11 additions & 0 deletions doc/sphinx/api/python/macho.rst
Original file line number Diff line number Diff line change
Expand Up @@ -482,3 +482,14 @@ VM_PROTECTIONS
:members:
:inherited-members:
:undoc-members:


----------

SYMBOL_ORIGINS
~~~~~~~~~~~~~~

.. autoclass:: lief.MachO.SYMBOL_ORIGINS
:members:
:inherited-members:
:undoc-members:
86 changes: 86 additions & 0 deletions examples/python/macho_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

terminal_columns = int(terminal_columns)
terminal_rows = int(terminal_rows)
EXIT_STATUS = 0

class exceptions_handler(object):
func = None
Expand All @@ -38,6 +39,9 @@ def __call__(self, *args, **kwargs):
try:
return self.func(*args, **kwargs)
except self.exceptions as e:
global EXIT_STATUS
print("{} raised: {}".format(self.func.__name__, e))
EXIT_STATUS = 1
if self.on_except_callback is not None:
self.on_except_callback(e)
else:
Expand Down Expand Up @@ -363,6 +367,47 @@ def print_dyld_info(binary):

print("")


@exceptions_handler(Exception)
def print_rebase_opcodes(binary):
print("== Rebase opcodes ==")

print(binary.dyld_info.show_rebases_opcodes)

print("")

@exceptions_handler(Exception)
def print_bind_opcodes(binary):
print("== Bind opcodes ==")

print(binary.dyld_info.show_bind_opcodes)

print("")

@exceptions_handler(Exception)
def print_weak_bind_opcodes(binary):
print("== Weak bind opcodes ==")

print(binary.dyld_info.show_weak_bind_opcodes)

print("")

@exceptions_handler(Exception)
def print_lazy_bind_opcodes(binary):
print("== Lazy bind opcodes ==")

print(binary.dyld_info.show_lazy_bind_opcodes)

print("")

@exceptions_handler(Exception)
def print_export_trie(binary):
print("== Export trie ==")

print(binary.dyld_info.show_export_trie)

print("")

@exceptions_handler(Exception)
def print_source_version(binary):
print("== Source Version ==")
Expand Down Expand Up @@ -506,6 +551,10 @@ def main():
action='store_true', dest='show_function_starts',
help='Display the FunctionStarts command')

parser.add_argument('--rebase-opcodes',
action='store_true', dest='show_rebase_opcodes',
help='Display the "Rebase" opcodes')

parser.add_argument('--source-version',
action='store_true', dest='show_source_version',
help="Display the 'Source Version' command")
Expand All @@ -522,6 +571,26 @@ def main():
action='store_true', dest='show_rpath_command',
help="Display the 'Rpath Command' command")

parser.add_argument('--bind-opcodes',
action='store_true', dest='show_bind_opcodes',
help='Display the "Bind" opcodes')

parser.add_argument('--weak-bind-opcodes',
action='store_true', dest='show_weak_bind_opcodes',
help='Display the "Weak Bind" opcodes')

parser.add_argument('--lazy-bind-opcodes',
action='store_true', dest='show_lazy_bind_opcodes',
help='Display the "Lazy Bind" opcodes')

parser.add_argument('--export-trie',
action='store_true', dest='show_export_trie',
help='Display the export trie')

parser.add_argument('--opcodes',
action='store_true', dest='show_opcodes',
help='Display the bind and rebase opcodes')

parser.add_argument("binary",
metavar="<macho-file>",
help='Target Mach-O File')
Expand Down Expand Up @@ -587,6 +656,23 @@ def main():
if (args.show_rpath_command or args.show_all) and binary.has_rpath:
print_rpath_command(binary)

if (args.show_rebase_opcodes or args.show_opcodes) and binary.has_dyld_info:
print_rebase_opcodes(binary)

if (args.show_bind_opcodes or args.show_opcodes) and binary.has_dyld_info:
print_bind_opcodes(binary)

if (args.show_weak_bind_opcodes or args.show_opcodes) and binary.has_dyld_info:
print_weak_bind_opcodes(binary)

if (args.show_lazy_bind_opcodes or args.show_opcodes) and binary.has_dyld_info:
print_lazy_bind_opcodes(binary)

if (args.show_export_trie or args.show_opcodes) and binary.has_dyld_info:
print_export_trie(binary)

sys.exit(EXIT_STATUS)


if __name__ == "__main__":
main()
27 changes: 26 additions & 1 deletion include/LIEF/MachO/DyldInfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <iostream>
#include <array>

#include "LIEF/BinaryStream/VectorStream.hpp"
#include "LIEF/visibility.h"
#include "LIEF/types.hpp"

Expand All @@ -46,9 +47,11 @@ class DLL_PUBLIC DyldInfo : public LoadCommand {
DyldInfo(void);
DyldInfo(const dyld_info_command *dyld_info_cmd);

DyldInfo& operator=(const DyldInfo& copy);
DyldInfo& operator=(DyldInfo other);
DyldInfo(const DyldInfo& copy);

void swap(DyldInfo& other);

virtual ~DyldInfo(void);

//! @brief *Rebase* information
Expand All @@ -73,6 +76,10 @@ class DLL_PUBLIC DyldInfo : public LoadCommand {
//! @brief Set new opcodes
void rebase_opcodes(const buffer_t& raw);


//! Return the rebase opcodes in a humman-readable way
std::string show_rebases_opcodes(void) const;

//! @brief *Bind* information
//!
//! Dyld binds an image during the loading process, if the image
Expand All @@ -96,6 +103,9 @@ class DLL_PUBLIC DyldInfo : public LoadCommand {
//! @brief Set new opcodes
void bind_opcodes(const buffer_t& raw);

//! Return the bind opcodes in a humman-readable way
std::string show_bind_opcodes(void) const;

//! @brief *Weak Bind* information
//!
//! Some C++ programs require dyld to unique symbols so that all
Expand All @@ -122,6 +132,9 @@ class DLL_PUBLIC DyldInfo : public LoadCommand {
//! @brief Set new opcodes
void weak_bind_opcodes(const buffer_t& raw);

//! Return the bind opcodes in a humman-readable way
std::string show_weak_bind_opcodes(void) const;

//! @brief *Lazy Bind* information
//!
//! Some uses of external symbols do not need to be bound immediately.
Expand All @@ -145,6 +158,9 @@ class DLL_PUBLIC DyldInfo : public LoadCommand {
//! @brief Set new opcodes
void lazy_bind_opcodes(const buffer_t& raw);

//! Return the lazy opcodes in a humman-readable way
std::string show_lazy_bind_opcodes(void) const;

//! @brief Iterator over BindingInfo entries
it_binding_info bindings(void);
it_const_binding_info bindings(void) const;
Expand Down Expand Up @@ -188,6 +204,9 @@ class DLL_PUBLIC DyldInfo : public LoadCommand {
//! @brief Set new trie
void export_trie(const buffer_t& raw);

//! Return the export trie in a humman-readable way
std::string show_export_trie(void) const;

void rebase(const info_t& info);
void bind(const info_t& info);
void weak_bind(const info_t& info);
Expand Down Expand Up @@ -217,6 +236,10 @@ class DLL_PUBLIC DyldInfo : public LoadCommand {
virtual std::ostream& print(std::ostream& os) const override;

private:
void show_bindings(std::ostream& os, const buffer_t& buffer, bool is_lazy = false) const;

void show_trie(std::ostream& output, std::string output_prefix, VectorStream& stream, uint64_t start, uint64_t current_offset, uint64_t end, const std::string& prefix) const;

info_t rebase_;
buffer_t rebase_opcodes_;

Expand All @@ -235,6 +258,8 @@ class DLL_PUBLIC DyldInfo : public LoadCommand {
export_info_t export_info_;
binding_info_t binding_info_;

Binary* binary_{nullptr};

};

}
Expand Down
1 change: 1 addition & 0 deletions include/LIEF/MachO/EnumToString.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ DLL_PUBLIC const char* to_string(BIND_SPECIAL_DYLIB e);
DLL_PUBLIC const char* to_string(BIND_OPCODES e);
DLL_PUBLIC const char* to_string(EXPORT_SYMBOL_KINDS e);
DLL_PUBLIC const char* to_string(VM_PROTECTIONS e);
DLL_PUBLIC const char* to_string(SYMBOL_ORIGINS e);

} // namespace MachO
} // namespace LIEF
Expand Down
2 changes: 2 additions & 0 deletions include/LIEF/MachO/LoadCommand.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class DLL_PUBLIC LoadCommand : public Visitable {
LoadCommand& operator=(const LoadCommand& copy);
LoadCommand(const LoadCommand& copy);

void swap(LoadCommand& other);

virtual ~LoadCommand(void);

LOAD_COMMAND_TYPES command(void) const;
Expand Down
4 changes: 4 additions & 0 deletions include/LIEF/MachO/Symbol.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ class DLL_PUBLIC Symbol : public LIEF::Symbol {

bool is_external(void) const;

SYMBOL_ORIGINS origin(void) const;

virtual void accept(Visitor& visitor) const override;

bool operator==(const Symbol& rhs) const;
Expand All @@ -87,6 +89,8 @@ class DLL_PUBLIC Symbol : public LIEF::Symbol {

BindingInfo* binding_info_;
ExportInfo* export_info_;

SYMBOL_ORIGINS origin_;
};

}
Expand Down
9 changes: 8 additions & 1 deletion include/LIEF/MachO/enums.inc
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ enum BIND_OPCODES {
};

enum EXPORT_SYMBOL_FLAGS {
EXPORT_SYMBOL_FLAGS_KIND_MASK = 0x03u,
EXPORT_SYMBOL_FLAGS_KIND_MASK = 0x03u, ///< Mask to access to EXPORT_SYMBOL_KINDS
EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION = 0x04u,
EXPORT_SYMBOL_FLAGS_REEXPORT = 0x08u,
EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER = 0x10u
Expand Down Expand Up @@ -387,6 +387,13 @@ enum RELOCATION_ORIGINS {
ORIGIN_RELOC_TABLE = 2,
};


enum SYMBOL_ORIGINS {
SYM_ORIGIN_UNKNOWN = 0,
SYM_ORIGIN_DYLD_EXPORT = 1,
SYM_ORIGIN_LC_SYMTAB = 2,
};

enum X86_RELOCATION {
GENERIC_RELOC_VANILLA = 0, /**< A generic relocation entry for both addresses contained in data and addresses contained in CPU instructions. */
GENERIC_RELOC_PAIR = 1, /**< The second relocation entry of a pair. */
Expand Down
Loading

0 comments on commit 5d56141

Please sign in to comment.