Skip to content

Commit

Permalink
Expose DataInCode
Browse files Browse the repository at this point in the history
  • Loading branch information
romainthomas committed Apr 2, 2018
1 parent 9cadce3 commit a16e1c4
Show file tree
Hide file tree
Showing 24 changed files with 718 additions and 1 deletion.
2 changes: 2 additions & 0 deletions api/python/MachO/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ set(LIEF_PYTHON_MACHO_SRC
"${CMAKE_CURRENT_LIST_DIR}/objects/pyParserConfig.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDynamicSymbolCommand.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyCodeSignature.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDataInCode.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDataCodeEntry.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyMachOStructures.cpp"
)

Expand Down
12 changes: 11 additions & 1 deletion api/python/MachO/objects/pyBinary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ void init_MachO_Binary_class(py::module& m) {
py::return_value_policy::reference)

.def_property_readonly("has_code_signature",
&Binary::has_dynamic_symbol_command,
&Binary::has_code_signature,
"``True`` if the binary is signed (i.e. has a " RST_CLASS_REF(lief.MachO.CodeSignature) " command)",
py::return_value_policy::reference_internal)

Expand All @@ -245,6 +245,16 @@ void init_MachO_Binary_class(py::module& m) {
"Return binary's " RST_CLASS_REF(lief.MachO.CodeSignature) " if any.",
py::return_value_policy::reference)

.def_property_readonly("has_data_in_code",
&Binary::has_data_in_code,
"``True`` if the binary has a " RST_CLASS_REF(lief.MachO.DataInCode) " command",
py::return_value_policy::reference_internal)

.def_property_readonly("data_in_code",
static_cast<no_const_getter<DataInCode&>>(&Binary::data_in_code),
"Return binary's " RST_CLASS_REF(lief.MachO.DataInCode) " if any.",
py::return_value_policy::reference)


.def("virtual_address_to_offset",
&Binary::virtual_address_to_offset,
Expand Down
86 changes: 86 additions & 0 deletions api/python/MachO/objects/pyDataCodeEntry.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <algorithm>

#include <string>
#include <sstream>

#include "LIEF/MachO/hash.hpp"
#include "LIEF/MachO/DataCodeEntry.hpp"
#include "LIEF/MachO/EnumToString.hpp"

#include "enums_wrapper.hpp"

#include "pyMachO.hpp"

#define PY_ENUM(x) LIEF::MachO::to_string(x), x

template<class T>
using getter_t = T (DataCodeEntry::*)(void) const;

template<class T>
using setter_t = void (DataCodeEntry::*)(T);


void init_MachO_DataCodeEntry_class(py::module& m) {


py::class_<DataCodeEntry, LIEF::Object> cls(m, "DataCodeEntry");

cls
.def_property("offset",
static_cast<getter_t<uint32_t>>(&DataCodeEntry::offset),
static_cast<setter_t<uint32_t>>(&DataCodeEntry::offset),
"Offset of the data")

.def_property("length",
static_cast<getter_t<uint16_t>>(&DataCodeEntry::length),
static_cast<setter_t<uint16_t>>(&DataCodeEntry::length),
"Length of the data")

.def_property("type",
static_cast<getter_t<DataCodeEntry::TYPES>>(&DataCodeEntry::type),
static_cast<setter_t<DataCodeEntry::TYPES>>(&DataCodeEntry::type),
"Type of the entry (" RST_CLASS_REF(lief.MachO.DataCodeEntry.TYPES) "")


.def("__eq__", &DataCodeEntry::operator==)
.def("__ne__", &DataCodeEntry::operator!=)
.def("__hash__",
[] (const DataCodeEntry& func) {
return Hash::hash(func);
})


.def("__str__",
[] (const DataCodeEntry& func)
{
std::ostringstream stream;
stream << func;
std::string str = stream.str();
return str;
});


LIEF::enum_<DataCodeEntry::TYPES>(cls, "TYPES")
.value(PY_ENUM(DataCodeEntry::TYPES::UNKNOWN))
.value(PY_ENUM(DataCodeEntry::TYPES::DATA))
.value(PY_ENUM(DataCodeEntry::TYPES::JUMP_TABLE_8))
.value(PY_ENUM(DataCodeEntry::TYPES::JUMP_TABLE_16))
.value(PY_ENUM(DataCodeEntry::TYPES::JUMP_TABLE_32))
.value(PY_ENUM(DataCodeEntry::TYPES::ABS_JUMP_TABLE_32));

}
76 changes: 76 additions & 0 deletions api/python/MachO/objects/pyDataInCode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <algorithm>

#include <string>
#include <sstream>

#include "LIEF/MachO/hash.hpp"
#include "LIEF/MachO/DataInCode.hpp"

#include "pyMachO.hpp"

template<class T>
using getter_t = T (DataInCode::*)(void) const;

template<class T>
using setter_t = void (DataInCode::*)(T);


void init_MachO_DataInCode_class(py::module& m) {

// Init Iterator
init_ref_iterator<DataInCode::it_entries>(m);

py::class_<DataInCode, LoadCommand>(m, "DataInCode")
.def_property("data_offset",
static_cast<getter_t<uint32_t>>(&DataInCode::data_offset),
static_cast<setter_t<uint32_t>>(&DataInCode::data_offset),
"Offset in the binary where signature starts")

.def_property("data_size",
static_cast<getter_t<uint32_t>>(&DataInCode::data_size),
static_cast<setter_t<uint32_t>>(&DataInCode::data_size),
"Size of the raw signature")

.def_property_readonly("entries",
static_cast<DataInCode::it_entries (DataInCode::*)(void)>(&DataInCode::entries),
"Iterator over " RST_CLASS_REF(lief.MachO.DataCodeEntry) "",
py::return_value_policy::reference_internal)

.def("add",
&DataInCode::add,
"Add an new " RST_CLASS_REF(lief.MachO.DataCodeEntry) "",
"entry"_a)

.def("__eq__", &DataInCode::operator==)
.def("__ne__", &DataInCode::operator!=)
.def("__hash__",
[] (const DataInCode& func) {
return Hash::hash(func);
})


.def("__str__",
[] (const DataInCode& func)
{
std::ostringstream stream;
stream << func;
std::string str = stream.str();
return str;
});

}
3 changes: 3 additions & 0 deletions api/python/MachO/pyMachO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ void init_MachO_module(py::module& m) {
init_MachO_DynamicSymbolCommand_class(LIEF_MachO_module);
init_MachO_CodeSignature_class(LIEF_MachO_module);

init_MachO_DataInCode_class(LIEF_MachO_module);
init_MachO_DataCodeEntry_class(LIEF_MachO_module);

// Enums
init_MachO_Structures_enum(LIEF_MachO_module);
}
2 changes: 2 additions & 0 deletions api/python/MachO/pyMachO.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ void init_MachO_ThreadCommand_class(py::module&);
void init_MachO_RPathCommand_class(py::module&);
void init_MachO_DynamicSymbolCommand_class(py::module&);
void init_MachO_CodeSignature_class(py::module&);
void init_MachO_DataInCode_class(py::module&);
void init_MachO_DataCodeEntry_class(py::module&);

// Enums
void init_MachO_Structures_enum(py::module&);
Expand Down
2 changes: 2 additions & 0 deletions api/python/enums_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

#include "LIEF/visibility.h"

namespace py = pybind11;

namespace LIEF {

template <class Type>
Expand Down
19 changes: 19 additions & 0 deletions doc/sphinx/api/cpp/macho.rst
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,25 @@ Code Signature

----------

Data In Code
************

.. doxygenclass:: LIEF::MachO::DataInCode
:project: lief

----------

Data Code Entry
****************

.. doxygenclass:: LIEF::MachO::DataCodeEntry
:project: lief

.. doxygenenum:: LIEF::MachO::DataCodeEntry::TYPES
:project: lief

----------

Utilities
*********

Expand Down
29 changes: 29 additions & 0 deletions doc/sphinx/api/python/macho.rst
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,35 @@ Code Signature

----------

Data In Code
************

.. autoclass:: lief.MachO.DataInCode
:members:
:inherited-members:
:undoc-members:

----------

Data Code Entry
***************

.. autoclass:: lief.MachO.DataCodeEntry
:members:
:inherited-members:
:undoc-members:


TYPES
~~~~~

.. autoclass:: lief.MachO.DataCodeEntry.TYPES
:members:
:inherited-members:
:undoc-members:

----------


Enums
*****
Expand Down
26 changes: 26 additions & 0 deletions examples/python/macho_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,25 @@ def print_function_starts(binary):

print("")

@exceptions_handler(Exception)
def print_data_in_code(binary):
format_str = "{:<13} {:<30}"
format_hex = "{:<13} 0x{:<28x}"
format_dec = "{:<13} {:<30d}"

print("== Data In Code ==")

datacode = binary.data_in_code

print(format_hex.format("Offset:", datacode.data_offset))
print(format_hex.format("Size:", datacode.data_size))
print("")
for entry in datacode.entries:
type_str = str(entry.type).split(".")[-1]
print("- {:<14}: 0x{:x} ({:d} bytes)".format(type_str, entry.offset, entry.length))
print("")




@exceptions_handler(Exception)
Expand Down Expand Up @@ -636,6 +655,10 @@ def main():
action='store_true', dest='show_dynamic_symbol_command',
help="Display the 'Symbol Command' command")

parser.add_argument('--data-in-code',
action='store_true', dest='show_data_in_code',
help="Display the 'Data In Code' command")

parser.add_argument('--bind-opcodes',
action='store_true', dest='show_bind_opcodes',
help='Display the "Bind" opcodes')
Expand Down Expand Up @@ -727,6 +750,9 @@ def main():
if (args.show_dynamic_symbol_command or args.show_all) and binary.has_dynamic_symbol_command:
print_dynamic_symbol_command(binary)

if (args.show_data_in_code or args.show_all) and binary.has_data_in_code:
print_data_in_code(binary)

if (args.show_rpath_command or args.show_all) and binary.has_rpath:
print_rpath_command(binary)

Expand Down
8 changes: 8 additions & 0 deletions include/LIEF/MachO/Binary.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "LIEF/MachO/ThreadCommand.hpp"
#include "LIEF/MachO/RPathCommand.hpp"
#include "LIEF/MachO/CodeSignature.hpp"
#include "LIEF/MachO/DataInCode.hpp"

namespace LIEF {
namespace MachO {
Expand Down Expand Up @@ -298,6 +299,13 @@ class LIEF_API Binary : public LIEF::Binary {
CodeSignature& code_signature(void);
const CodeSignature& code_signature(void) const;

//! @brief ``true`` if the binaryhas a MachO::DataInCode command.
bool has_data_in_code(void) const;

//! @brief Return the MachO::Signature
DataInCode& data_in_code(void);
const DataInCode& data_in_code(void) const;

template<class T>
LIEF_LOCAL bool has_command(void) const;

Expand Down
Loading

0 comments on commit a16e1c4

Please sign in to comment.