Skip to content
Permalink
Browse files
Parser Dyld Info in depth (binding, rebases, exports)
Binding and rebase bytes codes are now parsed as well as export info
trie. Through ``RelocationDyld`` we created kind of *virtual* relocation
to modeling relocation process performed by Dyld

API Changes (Python / C++)
  * MachO::RelocationDyld   - Added
  * MachO::RelocationObject - Added
  * MachO::Relocation       - Updated according to previous ones

  * MachO::ExportInfo       - Added
  * MachO::BindingInfo      - Added

  * MachO::DyldInfo::rebase_opcodes    - Added
  * MachO::DyldInfo::bindings          - Added
  * MachO::DyldInfo::bind_opcodes      - Added
  * MachO::DyldInfo::weak_bind_opcodes - Added
  * MachO::DyldInfo::lazy_bind_opcodes - Added
  * MachO::DyldInfo::exports           - Added
  * MachO::DyldInfo::export_trie       - Added

  * MachO::Symbol
    - Tied to MachO::BindingInfo (if any)
    - Tied to MachO::ExportInfo (if any)

  * MachO::Binary::relocations - Added
  * MachO::Binary::has_symbol  - Added
  * MachO::Binary::get_symbol  - Added

Resolve: #67
  • Loading branch information
romainthomas committed Jul 30, 2017
1 parent 8d25408 commit 782295b
Show file tree
Hide file tree
Showing 52 changed files with 3,791 additions and 311 deletions.
@@ -16,6 +16,10 @@ set(LIEF_PYTHON_MACHO_SRC
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDyldInfo.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyFunctionStarts.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyRelocation.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyRelocationObject.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyRelocationDyld.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyBindingInfo.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyExportInfo.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyMachOStructures.cpp"
)

@@ -23,6 +23,9 @@
template<class T>
using no_const_getter = T (Binary::*)(void);

template<class T, class P>
using no_const_func = T (Binary::*)(P);

void init_MachO_Binary_class(py::module& m) {


@@ -37,6 +40,11 @@ void init_MachO_Binary_class(py::module& m) {
"Return binary's " RST_CLASS_REF(lief.MachO.Section) "",
py::return_value_policy::reference_internal)

.def_property_readonly("relocations",
static_cast<no_const_getter<it_relocations>>(&Binary::relocations),
"Return an iterator over binary's " RST_CLASS_REF(lief.MachO.Relocation) "",
py::return_value_policy::reference_internal)

.def_property_readonly("segments",
static_cast<no_const_getter<it_segments>>(&Binary::segments),
"Return binary's " RST_CLASS_REF(lief.MachO.SegmentCommand) "",
@@ -52,6 +60,17 @@ void init_MachO_Binary_class(py::module& m) {
"Return binary's " RST_CLASS_REF(lief.MachO.Symbol) "",
py::return_value_policy::reference_internal)

.def("has_symbol",
&Binary::has_symbol,
"Check if a " RST_CLASS_REF(lief.MachO.Symbol) " with the given name exists",
"name"_a)

.def("get_symbol",
static_cast<no_const_func<Symbol&, const std::string&>>(&Binary::get_symbol),
"Return the " RST_CLASS_REF(lief.MachO.Symbol) " from the given name",
"name"_a,
py::return_value_policy::reference)

.def_property_readonly("imported_symbols",
static_cast<no_const_getter<it_imported_symbols>>(&Binary::get_imported_symbols),
"Return binary's " RST_CLASS_REF(lief.MachO.Symbol) " which are imported",
@@ -0,0 +1,121 @@
/* 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/visitors/Hash.hpp"
#include "LIEF/MachO/BindingInfo.hpp"

#include "pyMachO.hpp"

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

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


void init_MachO_BindingInfo_class(py::module& m) {

py::class_<BindingInfo>(m, "BindingInfo")

.def_property("binding_class",
static_cast<getter_t<BINDING_CLASS>>(&BindingInfo::binding_class),
static_cast<setter_t<BINDING_CLASS>>(&BindingInfo::binding_class),
"" RST_CLASS_REF(lief.MachO.BINDING_CLASS) " of the binding",
py::return_value_policy::reference_internal)

.def_property("address",
static_cast<getter_t<uint64_t>>(&BindingInfo::address),
static_cast<setter_t<uint64_t>>(&BindingInfo::address),
"Binding's address",
py::return_value_policy::reference_internal)

.def_property("binding_type",
static_cast<getter_t<BIND_TYPES>>(&BindingInfo::binding_type),
static_cast<setter_t<BIND_TYPES>>(&BindingInfo::binding_type),
"" RST_CLASS_REF(lief.MachO.BIND_TYPES) " of the binding\n"
"Most of the times it's :attr:`~lief.MachO.BIND_TYPES.POINTER`",
py::return_value_policy::reference_internal)


.def_property("library_ordinal",
static_cast<getter_t<int32_t>>(&BindingInfo::library_ordinal),
static_cast<setter_t<int32_t>>(&BindingInfo::library_ordinal),
py::return_value_policy::reference_internal)

.def_property("addend",
static_cast<getter_t<int64_t>>(&BindingInfo::addend),
static_cast<setter_t<int64_t>>(&BindingInfo::addend),
"Value added to the segment's virtual address when binding",
py::return_value_policy::reference_internal)

.def_property("weak_import",
static_cast<getter_t<bool>>(&BindingInfo::is_weak_import),
static_cast<setter_t<bool>>(&BindingInfo::set_weak_import),
py::return_value_policy::reference_internal)


.def_property_readonly("has_library",
&BindingInfo::has_library,
"``True`` if the binding info has a " RST_CLASS_REF(lief.MachO.DylibCommand) " associated with")

.def_property_readonly("library",
static_cast<DylibCommand& (BindingInfo::*)(void)>(&BindingInfo::library),
"" RST_CLASS_REF(lief.MachO.DylibCommand) " associated with the binding (if any)",
py::return_value_policy::reference)


.def_property_readonly("has_segment",
&BindingInfo::has_segment,
"``True`` if the binding info has a " RST_CLASS_REF(lief.MachO.SegmentCommand) " associated with")

.def_property_readonly("segment",
static_cast<SegmentCommand& (BindingInfo::*)(void)>(&BindingInfo::segment),
"" RST_CLASS_REF(lief.MachO.SegmentCommand) " associated with the binding (if any)",
py::return_value_policy::reference)


.def_property_readonly("has_symbol",
&BindingInfo::has_symbol,
"``True`` if the binding info has a " RST_CLASS_REF(lief.MachO.Symbol) " associated with")

.def_property_readonly("symbol",
static_cast<Symbol& (BindingInfo::*)(void)>(&BindingInfo::symbol),
"" RST_CLASS_REF(lief.MachO.Symbol) " associated with the binding (if any)",
py::return_value_policy::reference)


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


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

}
@@ -29,6 +29,8 @@ using getter_t = T (DyldInfo::*)(void) const;
template<class T>
using setter_t = void (DyldInfo::*)(T);

template<class T>
using no_const_getter = T (DyldInfo::*)(void);

void init_MachO_DyldInfo_class(py::module& m) {

@@ -53,6 +55,10 @@ void init_MachO_DyldInfo_class(py::module& m) {
"\t``/usr/include/mach-o/loader.h``\n",
py::return_value_policy::reference_internal)

.def_property("rebase_opcodes",
static_cast<getter_t<const buffer_t&>>(&DyldInfo::rebase_opcodes),
static_cast<setter_t<const buffer_t&>>(&DyldInfo::rebase_opcodes),
"Return Rebase's opcodes as ``list`` of bytes")

.def_property("bind",
static_cast<getter_t<const LIEF::MachO::DyldInfo::info_t&>>(&DyldInfo::bind),
@@ -75,6 +81,12 @@ void init_MachO_DyldInfo_class(py::module& m) {
py::return_value_policy::reference_internal)


.def_property("bind_opcodes",
static_cast<getter_t<const buffer_t&>>(&DyldInfo::bind_opcodes),
static_cast<setter_t<const buffer_t&>>(&DyldInfo::bind_opcodes),
"Return Binding's opcodes as ``list`` of bytes")


.def_property("weak_bind",
static_cast<getter_t<const LIEF::MachO::DyldInfo::info_t&>>(&DyldInfo::weak_bind),
static_cast<setter_t<const LIEF::MachO::DyldInfo::info_t&>>(&DyldInfo::weak_bind),
@@ -99,6 +111,12 @@ void init_MachO_DyldInfo_class(py::module& m) {
py::return_value_policy::reference_internal)


.def_property("weak_bind_opcodes",
static_cast<getter_t<const buffer_t&>>(&DyldInfo::weak_bind_opcodes),
static_cast<setter_t<const buffer_t&>>(&DyldInfo::weak_bind_opcodes),
"Return **Weak** binding's opcodes as ``list`` of bytes")


.def_property("lazy_bind",
static_cast<getter_t<const LIEF::MachO::DyldInfo::info_t&>>(&DyldInfo::lazy_bind),
static_cast<setter_t<const LIEF::MachO::DyldInfo::info_t&>>(&DyldInfo::lazy_bind),
@@ -120,6 +138,16 @@ void init_MachO_DyldInfo_class(py::module& m) {
py::return_value_policy::reference_internal)


.def_property("lazy_bind_opcodes",
static_cast<getter_t<const buffer_t&>>(&DyldInfo::lazy_bind_opcodes),
static_cast<setter_t<const buffer_t&>>(&DyldInfo::lazy_bind_opcodes),
"Return **lazy** binding's opcodes as ``list`` of bytes")

.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) "",
py::return_value_policy::reference_internal)

.def_property("export_info",
static_cast<getter_t<const LIEF::MachO::DyldInfo::info_t&>>(&DyldInfo::export_info),
static_cast<setter_t<const LIEF::MachO::DyldInfo::info_t&>>(&DyldInfo::export_info),
@@ -152,6 +180,16 @@ void init_MachO_DyldInfo_class(py::module& m) {
"\t``/usr/include/mach-o/loader.h``\n",
py::return_value_policy::reference_internal)

.def_property("export_trie",
static_cast<getter_t<const buffer_t&>>(&DyldInfo::export_trie),
static_cast<setter_t<const buffer_t&>>(&DyldInfo::export_trie),
"Return Export's trie as ``list`` of bytes")

.def_property_readonly("exports",
static_cast<no_const_getter<it_export_info>>(&DyldInfo::exports),
"Return an iterator over Dyld's " RST_CLASS_REF(lief.MachO.ExportInfo) "",
py::return_value_policy::reference_internal)

.def("set_rebase_offset",
&DyldInfo::set_rebase_offset,
"offset"_a)
@@ -0,0 +1,77 @@
/* 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/visitors/Hash.hpp"
#include "LIEF/MachO/ExportInfo.hpp"

#include "pyMachO.hpp"

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

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


void init_MachO_ExportInfo_class(py::module& m) {

py::class_<ExportInfo>(m, "ExportInfo")

.def_property_readonly("node_offset",
static_cast<getter_t<uint64_t>>(&ExportInfo::node_offset))

.def_property("flags",
static_cast<getter_t<uint64_t>>(&ExportInfo::flags),
static_cast<setter_t<uint64_t>>(&ExportInfo::flags),
py::return_value_policy::reference_internal)

.def_property("address",
static_cast<getter_t<uint64_t>>(&ExportInfo::address),
static_cast<setter_t<uint64_t>>(&ExportInfo::address),
py::return_value_policy::reference_internal)

.def_property_readonly("has_symbol",
&ExportInfo::has_symbol,
"``True`` if the export info has a " RST_CLASS_REF(lief.MachO.Symbol) " associated with")

.def_property_readonly("symbol",
static_cast<Symbol& (ExportInfo::*)(void)>(&ExportInfo::symbol),
"" RST_CLASS_REF(lief.MachO.Symbol) " associated with the export (if any)",
py::return_value_policy::reference)


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


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

}

0 comments on commit 782295b

Please sign in to comment.