Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Parse Mach-O relocations and add MachO API to retrieve section from name
API Update:
  lief.MachO.Section.relocations - to access to the relocations
  lief.MachO.binary.get_section - Get section from name
  lief.MachO.binary.has_section -Check if section with given name exists

Resolve #57
  • Loading branch information
romainthomas committed Jul 17, 2017
1 parent 114616b commit 29c8157
Show file tree
Hide file tree
Showing 30 changed files with 1,215 additions and 101 deletions.
1 change: 1 addition & 0 deletions api/python/MachO/CMakeLists.txt
Expand Up @@ -14,6 +14,7 @@ set(LIEF_PYTHON_MACHO_SRC
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDylinker.cpp"
"${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}/pyMachOStructures.cpp"
)

Expand Down
11 changes: 11 additions & 0 deletions api/python/MachO/objects/pyBinary.cpp
Expand Up @@ -164,6 +164,17 @@ void init_MachO_Binary_class(py::module& m) {
"Convert the virtual address to an offset in the binary",
"virtual_address"_a)

.def("has_section",
&Binary::has_section,
"Check if a section with the given name exists",
"name"_a)

.def("get_section",
static_cast<Section& (Binary::*)(const std::string&)>(&Binary::get_section),
"Return the section from the given name",
"name"_a,
py::return_value_policy::reference)


.def("__str__",
[] (const Binary& binary)
Expand Down
136 changes: 136 additions & 0 deletions api/python/MachO/objects/pyRelocation.cpp
@@ -0,0 +1,136 @@
/* 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/Relocation.hpp"

#include "pyMachO.hpp"

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

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


void init_MachO_Relocation_class(py::module& m) {

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

.def_property("address",
static_cast<getter_t<uint32_t>>(&Relocation::address),
static_cast<setter_t<uint32_t>>(&Relocation::address),
"For :attr:`~lief.MachO.FILE_TYPES.OBJECT` this is an "
"offset from the start of the " RST_CLASS_REF(lief.MachO.Section) " "
"to the item containing the address requiring relocation.",
py::return_value_policy::reference_internal)

.def_property("pc_relative",
static_cast<getter_t<bool>>(&Relocation::is_pc_relative),
static_cast<setter_t<bool>>(&Relocation::pc_relative),
"Indicates whether the item containing the address to be "
"relocated is part of a CPU instruction that uses PC-relative addressing.\n\n"

"For addresses contained in PC-relative instructions, the CPU adds the address of "
"the instruction to the address contained in the instruction.",
py::return_value_policy::reference_internal)

.def_property("size",
static_cast<getter_t<uint8_t>>(&Relocation::size),
static_cast<setter_t<uint8_t>>(&Relocation::size),
"Indicates the length of the item containing the address to be relocated.\n\n"

"The following table lists values and the corresponding address length:\n"
"\t * 0: 1 byte\n"
"\t * 1: 2 byte\n"
"\t * 2: 4 byte\n"
"\t * 3: 4 byte\n",
py::return_value_policy::reference_internal)

.def_property("type",
static_cast<getter_t<uint8_t>>(&Relocation::type),
static_cast<setter_t<uint8_t>>(&Relocation::type),
"Type of the relocation according to the :attr:`~lief.MachO.Relocation.architecture`\n\n"

"See:\n"
"\t * " RST_CLASS_REF(lief.MachO.X86_RELOCATION) "\n"
"\t * " RST_CLASS_REF(lief.MachO.X86_64_RELOCATION) "\n"
"\t * " RST_CLASS_REF(lief.MachO.PPC_RELOCATION) "\n"
"\t * " RST_CLASS_REF(lief.MachO.ARM_RELOCATION) "\n"
"\t * " RST_CLASS_REF(lief.MachO.ARM64_RELOCATION) "\n",
py::return_value_policy::reference_internal)

.def_property("value",
static_cast<getter_t<int32_t>>(&Relocation::value),
static_cast<setter_t<int32_t>>(&Relocation::value),
"For **scattered** relocations, the address of the relocatable expression "
"for the item in the file that needs to be updated if the address is changed.\n\n"

"For relocatable expressions with the difference of two section addresses, "
"the address from which to subtract (in mathematical terms, the minuend) "
"is contained in the first relocation entry and the address to subtract (the subtrahend) "
"is contained in the second relocation entry.",
py::return_value_policy::reference_internal)


.def_property_readonly("architecture",
&Relocation::architecture,
"" RST_CLASS_REF(lief.MachO.CPU_TYPES) " of the relocation")

.def_property_readonly("is_scattered",
&Relocation::is_scattered,
"``True`` if the relocation is a scattered one")

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

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

.def_property_readonly("has_section",
&Relocation::has_section,
"``True`` if the relocation has a " RST_CLASS_REF(lief.MachO.Section) " associated with")

.def_property_readonly("section",
static_cast<Section& (Relocation::*)(void)>(&Relocation::section),
"" RST_CLASS_REF(lief.MachO.Section) " associated with the relocation (if any)",
py::return_value_policy::reference)

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


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

}
8 changes: 8 additions & 0 deletions api/python/MachO/objects/pySection.cpp
Expand Up @@ -29,6 +29,9 @@ using getter_t = T (Section::*)(void) const;
template<class T>
using setter_t = void (Section::*)(T);

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

void init_MachO_Section_class(py::module& m) {

py::class_<Section, LIEF::Section>(m, "Section")
Expand All @@ -54,6 +57,11 @@ void init_MachO_Section_class(py::module& m) {
static_cast<setter_t<SECTION_TYPES>>(&Section::type),
"")

.def_property_readonly("relocations",
static_cast<no_const_getter<it_relocations>>(&Section::relocations),
"Iterator over " RST_CLASS_REF(lief.MachO.Relocation) " (if any)",
py::return_value_policy::reference_internal)


.def("__eq__", &Section::operator==)
.def("__ne__", &Section::operator!=)
Expand Down
1 change: 1 addition & 0 deletions api/python/MachO/pyMachO.cpp
Expand Up @@ -40,6 +40,7 @@ void init_MachO_module(py::module& m) {
init_MachO_DyldInfo_class(LIEF_MachO_module);
init_MachO_FunctionStarts_class(LIEF_MachO_module);
init_MachO_SourceVersion_class(LIEF_MachO_module);
init_MachO_Relocation_class(LIEF_MachO_module);


// Enums
Expand Down
1 change: 1 addition & 0 deletions api/python/MachO/pyMachO.hpp
Expand Up @@ -40,6 +40,7 @@ void init_MachO_DylinkerCommand_class(py::module&);
void init_MachO_DyldInfo_class(py::module&);
void init_MachO_FunctionStarts_class(py::module&);
void init_MachO_SourceVersion_class(py::module&);
void init_MachO_Relocation_class(py::module&);

// Enums
void init_MachO_Structures_enum(py::module&);
Expand Down
78 changes: 78 additions & 0 deletions api/python/MachO/pyMachOStructures.cpp
Expand Up @@ -166,4 +166,82 @@ void init_MachO_Structures_enum(py::module& m) {
.value(PY_ENUM(LIEF::MachO::SECTION_TYPES::S_THREAD_LOCAL_VARIABLE_POINTERS))
.value(PY_ENUM(LIEF::MachO::SECTION_TYPES::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS))
.export_values();


py::enum_<LIEF::MachO::X86_RELOCATION>(m, "X86_RELOCATION")
.value(PY_ENUM(LIEF::MachO::X86_RELOCATION::GENERIC_RELOC_VANILLA))
.value(PY_ENUM(LIEF::MachO::X86_RELOCATION::GENERIC_RELOC_PAIR))
.value(PY_ENUM(LIEF::MachO::X86_RELOCATION::GENERIC_RELOC_SECTDIFF))
.value(PY_ENUM(LIEF::MachO::X86_RELOCATION::GENERIC_RELOC_PB_LA_PTR))
.value(PY_ENUM(LIEF::MachO::X86_RELOCATION::GENERIC_RELOC_LOCAL_SECTDIFF))
.value(PY_ENUM(LIEF::MachO::X86_RELOCATION::GENERIC_RELOC_TLV))
.export_values();

py::enum_<LIEF::MachO::X86_64_RELOCATION>(m, "X86_64_RELOCATION")
.value(PY_ENUM(LIEF::MachO::X86_64_RELOCATION::X86_64_RELOC_UNSIGNED))
.value(PY_ENUM(LIEF::MachO::X86_64_RELOCATION::X86_64_RELOC_SIGNED))
.value(PY_ENUM(LIEF::MachO::X86_64_RELOCATION::X86_64_RELOC_BRANCH))
.value(PY_ENUM(LIEF::MachO::X86_64_RELOCATION::X86_64_RELOC_GOT_LOAD))
.value(PY_ENUM(LIEF::MachO::X86_64_RELOCATION::X86_64_RELOC_GOT))
.value(PY_ENUM(LIEF::MachO::X86_64_RELOCATION::X86_64_RELOC_SUBTRACTOR))
.value(PY_ENUM(LIEF::MachO::X86_64_RELOCATION::X86_64_RELOC_SIGNED_1))
.value(PY_ENUM(LIEF::MachO::X86_64_RELOCATION::X86_64_RELOC_SIGNED_2))
.value(PY_ENUM(LIEF::MachO::X86_64_RELOCATION::X86_64_RELOC_SIGNED_4))
.value(PY_ENUM(LIEF::MachO::X86_64_RELOCATION::X86_64_RELOC_TLV))
.export_values();

py::enum_<LIEF::MachO::PPC_RELOCATION>(m, "PPC_RELOCATION")
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_VANILLA))
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_PAIR))
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_BR14))
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_BR24))
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_HI16))
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_LO16))
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_HA16))
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_LO14))
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_SECTDIFF))
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_PB_LA_PTR))
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_HI16_SECTDIFF))
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_LO16_SECTDIFF))
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_HA16_SECTDIFF))
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_JBSR))
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_LO14_SECTDIFF))
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_LOCAL_SECTDIFF))
.export_values();

py::enum_<LIEF::MachO::ARM_RELOCATION>(m, "ARM_RELOCATION")
.value(PY_ENUM(LIEF::MachO::ARM_RELOCATION::ARM_RELOC_VANILLA))
.value(PY_ENUM(LIEF::MachO::ARM_RELOCATION::ARM_RELOC_PAIR))
.value(PY_ENUM(LIEF::MachO::ARM_RELOCATION::ARM_RELOC_SECTDIFF))
.value(PY_ENUM(LIEF::MachO::ARM_RELOCATION::ARM_RELOC_LOCAL_SECTDIFF))
.value(PY_ENUM(LIEF::MachO::ARM_RELOCATION::ARM_RELOC_PB_LA_PTR))
.value(PY_ENUM(LIEF::MachO::ARM_RELOCATION::ARM_RELOC_BR24))
.value(PY_ENUM(LIEF::MachO::ARM_RELOCATION::ARM_THUMB_RELOC_BR22))
.value(PY_ENUM(LIEF::MachO::ARM_RELOCATION::ARM_THUMB_32BIT_BRANCH))
.value(PY_ENUM(LIEF::MachO::ARM_RELOCATION::ARM_RELOC_HALF))
.value(PY_ENUM(LIEF::MachO::ARM_RELOCATION::ARM_RELOC_HALF_SECTDIFF))
.export_values();

py::enum_<LIEF::MachO::ARM64_RELOCATION>(m, "ARM64_RELOCATION")
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_UNSIGNED))
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_SUBTRACTOR))
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_BRANCH26))
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_PAGE21))
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_PAGEOFF12))
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_GOT_LOAD_PAGE21))
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_GOT_LOAD_PAGEOFF12))
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_POINTER_TO_GOT))
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_TLVP_LOAD_PAGE21))
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_TLVP_LOAD_PAGEOFF12))
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_ADDEND))
.export_values();









}
1 change: 1 addition & 0 deletions api/python/pyIterators.cpp
Expand Up @@ -61,6 +61,7 @@ void init_LIEF_iterators(py::module& m) {
// MachO
// =====
#if defined(LIEF_MACHO_MODULE)
init_ref_iterator<LIEF::MachO::it_relocations>(m);
init_ref_iterator<LIEF::MachO::it_commands>(m);
init_ref_iterator<LIEF::MachO::it_symbols>(m);
init_ref_iterator<LIEF::filter_iterator<LIEF::MachO::symbols_t>>(m);
Expand Down
2 changes: 0 additions & 2 deletions doc/sphinx/api/cpp/elf.rst
Expand Up @@ -156,11 +156,9 @@ Enums
.. doxygenenum:: LIEF::ELF::ARCH
:project: lief


.. doxygenenum:: LIEF::ELF::IDENTITY
:project: lief


.. doxygenenum:: LIEF::ELF::E_TYPE
:project: lief

Expand Down
65 changes: 65 additions & 0 deletions doc/sphinx/api/cpp/macho.rst
Expand Up @@ -140,3 +140,68 @@ Source Version

.. doxygenclass:: LIEF::MachO::SourceVersion
:project: lief

----------

Relocation
**********

.. doxygenclass:: LIEF::MachO::Relocation
:project: lief

----------


Enums
*****

.. doxygenenum:: LIEF::MachO::MACHO_TYPES
:project: lief

.. doxygenenum:: LIEF::MachO::FILE_TYPES
:project: lief

.. doxygenenum:: LIEF::MachO::HEADER_FLAGS
:project: lief

.. doxygenenum:: LIEF::MachO::LOAD_COMMAND_TYPES
:project: lief

.. doxygenenum:: LIEF::MachO::SEGMENTS_FLAGS
:project: lief

.. doxygenenum:: LIEF::MachO::SECTION_FLAGS_HELPER
:project: lief

.. doxygenenum:: LIEF::MachO::SECTION_TYPES
:project: lief

.. doxygenenum:: LIEF::MachO::SECTION_FLAGS
:project: lief

.. doxygenenum:: LIEF::MachO::SYMBOL_TYPES
:project: lief

.. doxygenenum:: LIEF::MachO::SYMBOL_DESCRIPTIONS
:project: lief

.. doxygenenum:: LIEF::MachO::X86_RELOCATION
:project: lief

.. doxygenenum:: LIEF::MachO::X86_64_RELOCATION
:project: lief

.. doxygenenum:: LIEF::MachO::PPC_RELOCATION
:project: lief

.. doxygenenum:: LIEF::MachO::ARM_RELOCATION
:project: lief

.. doxygenenum:: LIEF::MachO::ARM64_RELOCATION
:project: lief

.. doxygenenum:: LIEF::MachO::CPU_TYPES
:project: lief

.. doxygenenum:: LIEF::MachO::CPU_SUBTYPES_X86
:project: lief

0 comments on commit 29c8157

Please sign in to comment.