Skip to content

Commit 29c8157

Browse files
committed
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
1 parent 114616b commit 29c8157

30 files changed

+1215
-101
lines changed

api/python/MachO/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ set(LIEF_PYTHON_MACHO_SRC
1414
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDylinker.cpp"
1515
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDyldInfo.cpp"
1616
"${CMAKE_CURRENT_LIST_DIR}/objects/pyFunctionStarts.cpp"
17+
"${CMAKE_CURRENT_LIST_DIR}/objects/pyRelocation.cpp"
1718
"${CMAKE_CURRENT_LIST_DIR}/pyMachOStructures.cpp"
1819
)
1920

api/python/MachO/objects/pyBinary.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,17 @@ void init_MachO_Binary_class(py::module& m) {
164164
"Convert the virtual address to an offset in the binary",
165165
"virtual_address"_a)
166166

167+
.def("has_section",
168+
&Binary::has_section,
169+
"Check if a section with the given name exists",
170+
"name"_a)
171+
172+
.def("get_section",
173+
static_cast<Section& (Binary::*)(const std::string&)>(&Binary::get_section),
174+
"Return the section from the given name",
175+
"name"_a,
176+
py::return_value_policy::reference)
177+
167178

168179
.def("__str__",
169180
[] (const Binary& binary)
+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/* Copyright 2017 R. Thomas
2+
* Copyright 2017 Quarkslab
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include <algorithm>
17+
18+
#include <string>
19+
#include <sstream>
20+
21+
#include "LIEF/visitors/Hash.hpp"
22+
#include "LIEF/MachO/Relocation.hpp"
23+
24+
#include "pyMachO.hpp"
25+
26+
template<class T>
27+
using getter_t = T (Relocation::*)(void) const;
28+
29+
template<class T>
30+
using setter_t = void (Relocation::*)(T);
31+
32+
33+
void init_MachO_Relocation_class(py::module& m) {
34+
35+
py::class_<Relocation>(m, "Relocation")
36+
37+
.def_property("address",
38+
static_cast<getter_t<uint32_t>>(&Relocation::address),
39+
static_cast<setter_t<uint32_t>>(&Relocation::address),
40+
"For :attr:`~lief.MachO.FILE_TYPES.OBJECT` this is an "
41+
"offset from the start of the " RST_CLASS_REF(lief.MachO.Section) " "
42+
"to the item containing the address requiring relocation.",
43+
py::return_value_policy::reference_internal)
44+
45+
.def_property("pc_relative",
46+
static_cast<getter_t<bool>>(&Relocation::is_pc_relative),
47+
static_cast<setter_t<bool>>(&Relocation::pc_relative),
48+
"Indicates whether the item containing the address to be "
49+
"relocated is part of a CPU instruction that uses PC-relative addressing.\n\n"
50+
51+
"For addresses contained in PC-relative instructions, the CPU adds the address of "
52+
"the instruction to the address contained in the instruction.",
53+
py::return_value_policy::reference_internal)
54+
55+
.def_property("size",
56+
static_cast<getter_t<uint8_t>>(&Relocation::size),
57+
static_cast<setter_t<uint8_t>>(&Relocation::size),
58+
"Indicates the length of the item containing the address to be relocated.\n\n"
59+
60+
"The following table lists values and the corresponding address length:\n"
61+
"\t * 0: 1 byte\n"
62+
"\t * 1: 2 byte\n"
63+
"\t * 2: 4 byte\n"
64+
"\t * 3: 4 byte\n",
65+
py::return_value_policy::reference_internal)
66+
67+
.def_property("type",
68+
static_cast<getter_t<uint8_t>>(&Relocation::type),
69+
static_cast<setter_t<uint8_t>>(&Relocation::type),
70+
"Type of the relocation according to the :attr:`~lief.MachO.Relocation.architecture`\n\n"
71+
72+
"See:\n"
73+
"\t * " RST_CLASS_REF(lief.MachO.X86_RELOCATION) "\n"
74+
"\t * " RST_CLASS_REF(lief.MachO.X86_64_RELOCATION) "\n"
75+
"\t * " RST_CLASS_REF(lief.MachO.PPC_RELOCATION) "\n"
76+
"\t * " RST_CLASS_REF(lief.MachO.ARM_RELOCATION) "\n"
77+
"\t * " RST_CLASS_REF(lief.MachO.ARM64_RELOCATION) "\n",
78+
py::return_value_policy::reference_internal)
79+
80+
.def_property("value",
81+
static_cast<getter_t<int32_t>>(&Relocation::value),
82+
static_cast<setter_t<int32_t>>(&Relocation::value),
83+
"For **scattered** relocations, the address of the relocatable expression "
84+
"for the item in the file that needs to be updated if the address is changed.\n\n"
85+
86+
"For relocatable expressions with the difference of two section addresses, "
87+
"the address from which to subtract (in mathematical terms, the minuend) "
88+
"is contained in the first relocation entry and the address to subtract (the subtrahend) "
89+
"is contained in the second relocation entry.",
90+
py::return_value_policy::reference_internal)
91+
92+
93+
.def_property_readonly("architecture",
94+
&Relocation::architecture,
95+
"" RST_CLASS_REF(lief.MachO.CPU_TYPES) " of the relocation")
96+
97+
.def_property_readonly("is_scattered",
98+
&Relocation::is_scattered,
99+
"``True`` if the relocation is a scattered one")
100+
101+
.def_property_readonly("has_symbol",
102+
&Relocation::has_symbol,
103+
"``True`` if the relocation has a " RST_CLASS_REF(lief.MachO.Symbol) " associated with")
104+
105+
.def_property_readonly("symbol",
106+
static_cast<Symbol& (Relocation::*)(void)>(&Relocation::symbol),
107+
"" RST_CLASS_REF(lief.MachO.Symbol) " associated with the relocation (if any)",
108+
py::return_value_policy::reference)
109+
110+
.def_property_readonly("has_section",
111+
&Relocation::has_section,
112+
"``True`` if the relocation has a " RST_CLASS_REF(lief.MachO.Section) " associated with")
113+
114+
.def_property_readonly("section",
115+
static_cast<Section& (Relocation::*)(void)>(&Relocation::section),
116+
"" RST_CLASS_REF(lief.MachO.Section) " associated with the relocation (if any)",
117+
py::return_value_policy::reference)
118+
119+
.def("__eq__", &Relocation::operator==)
120+
.def("__ne__", &Relocation::operator!=)
121+
.def("__hash__",
122+
[] (const Relocation& relocation) {
123+
return LIEF::Hash::hash(relocation);
124+
})
125+
126+
127+
.def("__str__",
128+
[] (const Relocation& relocation)
129+
{
130+
std::ostringstream stream;
131+
stream << relocation;
132+
std::string str = stream.str();
133+
return str;
134+
});
135+
136+
}

api/python/MachO/objects/pySection.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ using getter_t = T (Section::*)(void) const;
2929
template<class T>
3030
using setter_t = void (Section::*)(T);
3131

32+
template<class T>
33+
using no_const_getter = T (Section::*)(void);
34+
3235
void init_MachO_Section_class(py::module& m) {
3336

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

60+
.def_property_readonly("relocations",
61+
static_cast<no_const_getter<it_relocations>>(&Section::relocations),
62+
"Iterator over " RST_CLASS_REF(lief.MachO.Relocation) " (if any)",
63+
py::return_value_policy::reference_internal)
64+
5765

5866
.def("__eq__", &Section::operator==)
5967
.def("__ne__", &Section::operator!=)

api/python/MachO/pyMachO.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ void init_MachO_module(py::module& m) {
4040
init_MachO_DyldInfo_class(LIEF_MachO_module);
4141
init_MachO_FunctionStarts_class(LIEF_MachO_module);
4242
init_MachO_SourceVersion_class(LIEF_MachO_module);
43+
init_MachO_Relocation_class(LIEF_MachO_module);
4344

4445

4546
// Enums

api/python/MachO/pyMachO.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ void init_MachO_DylinkerCommand_class(py::module&);
4040
void init_MachO_DyldInfo_class(py::module&);
4141
void init_MachO_FunctionStarts_class(py::module&);
4242
void init_MachO_SourceVersion_class(py::module&);
43+
void init_MachO_Relocation_class(py::module&);
4344

4445
// Enums
4546
void init_MachO_Structures_enum(py::module&);

api/python/MachO/pyMachOStructures.cpp

+78
Original file line numberDiff line numberDiff line change
@@ -166,4 +166,82 @@ void init_MachO_Structures_enum(py::module& m) {
166166
.value(PY_ENUM(LIEF::MachO::SECTION_TYPES::S_THREAD_LOCAL_VARIABLE_POINTERS))
167167
.value(PY_ENUM(LIEF::MachO::SECTION_TYPES::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS))
168168
.export_values();
169+
170+
171+
py::enum_<LIEF::MachO::X86_RELOCATION>(m, "X86_RELOCATION")
172+
.value(PY_ENUM(LIEF::MachO::X86_RELOCATION::GENERIC_RELOC_VANILLA))
173+
.value(PY_ENUM(LIEF::MachO::X86_RELOCATION::GENERIC_RELOC_PAIR))
174+
.value(PY_ENUM(LIEF::MachO::X86_RELOCATION::GENERIC_RELOC_SECTDIFF))
175+
.value(PY_ENUM(LIEF::MachO::X86_RELOCATION::GENERIC_RELOC_PB_LA_PTR))
176+
.value(PY_ENUM(LIEF::MachO::X86_RELOCATION::GENERIC_RELOC_LOCAL_SECTDIFF))
177+
.value(PY_ENUM(LIEF::MachO::X86_RELOCATION::GENERIC_RELOC_TLV))
178+
.export_values();
179+
180+
py::enum_<LIEF::MachO::X86_64_RELOCATION>(m, "X86_64_RELOCATION")
181+
.value(PY_ENUM(LIEF::MachO::X86_64_RELOCATION::X86_64_RELOC_UNSIGNED))
182+
.value(PY_ENUM(LIEF::MachO::X86_64_RELOCATION::X86_64_RELOC_SIGNED))
183+
.value(PY_ENUM(LIEF::MachO::X86_64_RELOCATION::X86_64_RELOC_BRANCH))
184+
.value(PY_ENUM(LIEF::MachO::X86_64_RELOCATION::X86_64_RELOC_GOT_LOAD))
185+
.value(PY_ENUM(LIEF::MachO::X86_64_RELOCATION::X86_64_RELOC_GOT))
186+
.value(PY_ENUM(LIEF::MachO::X86_64_RELOCATION::X86_64_RELOC_SUBTRACTOR))
187+
.value(PY_ENUM(LIEF::MachO::X86_64_RELOCATION::X86_64_RELOC_SIGNED_1))
188+
.value(PY_ENUM(LIEF::MachO::X86_64_RELOCATION::X86_64_RELOC_SIGNED_2))
189+
.value(PY_ENUM(LIEF::MachO::X86_64_RELOCATION::X86_64_RELOC_SIGNED_4))
190+
.value(PY_ENUM(LIEF::MachO::X86_64_RELOCATION::X86_64_RELOC_TLV))
191+
.export_values();
192+
193+
py::enum_<LIEF::MachO::PPC_RELOCATION>(m, "PPC_RELOCATION")
194+
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_VANILLA))
195+
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_PAIR))
196+
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_BR14))
197+
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_BR24))
198+
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_HI16))
199+
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_LO16))
200+
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_HA16))
201+
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_LO14))
202+
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_SECTDIFF))
203+
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_PB_LA_PTR))
204+
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_HI16_SECTDIFF))
205+
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_LO16_SECTDIFF))
206+
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_HA16_SECTDIFF))
207+
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_JBSR))
208+
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_LO14_SECTDIFF))
209+
.value(PY_ENUM(LIEF::MachO::PPC_RELOCATION::PPC_RELOC_LOCAL_SECTDIFF))
210+
.export_values();
211+
212+
py::enum_<LIEF::MachO::ARM_RELOCATION>(m, "ARM_RELOCATION")
213+
.value(PY_ENUM(LIEF::MachO::ARM_RELOCATION::ARM_RELOC_VANILLA))
214+
.value(PY_ENUM(LIEF::MachO::ARM_RELOCATION::ARM_RELOC_PAIR))
215+
.value(PY_ENUM(LIEF::MachO::ARM_RELOCATION::ARM_RELOC_SECTDIFF))
216+
.value(PY_ENUM(LIEF::MachO::ARM_RELOCATION::ARM_RELOC_LOCAL_SECTDIFF))
217+
.value(PY_ENUM(LIEF::MachO::ARM_RELOCATION::ARM_RELOC_PB_LA_PTR))
218+
.value(PY_ENUM(LIEF::MachO::ARM_RELOCATION::ARM_RELOC_BR24))
219+
.value(PY_ENUM(LIEF::MachO::ARM_RELOCATION::ARM_THUMB_RELOC_BR22))
220+
.value(PY_ENUM(LIEF::MachO::ARM_RELOCATION::ARM_THUMB_32BIT_BRANCH))
221+
.value(PY_ENUM(LIEF::MachO::ARM_RELOCATION::ARM_RELOC_HALF))
222+
.value(PY_ENUM(LIEF::MachO::ARM_RELOCATION::ARM_RELOC_HALF_SECTDIFF))
223+
.export_values();
224+
225+
py::enum_<LIEF::MachO::ARM64_RELOCATION>(m, "ARM64_RELOCATION")
226+
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_UNSIGNED))
227+
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_SUBTRACTOR))
228+
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_BRANCH26))
229+
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_PAGE21))
230+
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_PAGEOFF12))
231+
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_GOT_LOAD_PAGE21))
232+
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_GOT_LOAD_PAGEOFF12))
233+
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_POINTER_TO_GOT))
234+
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_TLVP_LOAD_PAGE21))
235+
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_TLVP_LOAD_PAGEOFF12))
236+
.value(PY_ENUM(LIEF::MachO::ARM64_RELOCATION::ARM64_RELOC_ADDEND))
237+
.export_values();
238+
239+
240+
241+
242+
243+
244+
245+
246+
169247
}

api/python/pyIterators.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ void init_LIEF_iterators(py::module& m) {
6161
// MachO
6262
// =====
6363
#if defined(LIEF_MACHO_MODULE)
64+
init_ref_iterator<LIEF::MachO::it_relocations>(m);
6465
init_ref_iterator<LIEF::MachO::it_commands>(m);
6566
init_ref_iterator<LIEF::MachO::it_symbols>(m);
6667
init_ref_iterator<LIEF::filter_iterator<LIEF::MachO::symbols_t>>(m);

doc/sphinx/api/cpp/elf.rst

-2
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,9 @@ Enums
156156
.. doxygenenum:: LIEF::ELF::ARCH
157157
:project: lief
158158

159-
160159
.. doxygenenum:: LIEF::ELF::IDENTITY
161160
:project: lief
162161

163-
164162
.. doxygenenum:: LIEF::ELF::E_TYPE
165163
:project: lief
166164

doc/sphinx/api/cpp/macho.rst

+65
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,68 @@ Source Version
140140

141141
.. doxygenclass:: LIEF::MachO::SourceVersion
142142
:project: lief
143+
144+
----------
145+
146+
Relocation
147+
**********
148+
149+
.. doxygenclass:: LIEF::MachO::Relocation
150+
:project: lief
151+
152+
----------
153+
154+
155+
Enums
156+
*****
157+
158+
.. doxygenenum:: LIEF::MachO::MACHO_TYPES
159+
:project: lief
160+
161+
.. doxygenenum:: LIEF::MachO::FILE_TYPES
162+
:project: lief
163+
164+
.. doxygenenum:: LIEF::MachO::HEADER_FLAGS
165+
:project: lief
166+
167+
.. doxygenenum:: LIEF::MachO::LOAD_COMMAND_TYPES
168+
:project: lief
169+
170+
.. doxygenenum:: LIEF::MachO::SEGMENTS_FLAGS
171+
:project: lief
172+
173+
.. doxygenenum:: LIEF::MachO::SECTION_FLAGS_HELPER
174+
:project: lief
175+
176+
.. doxygenenum:: LIEF::MachO::SECTION_TYPES
177+
:project: lief
178+
179+
.. doxygenenum:: LIEF::MachO::SECTION_FLAGS
180+
:project: lief
181+
182+
.. doxygenenum:: LIEF::MachO::SYMBOL_TYPES
183+
:project: lief
184+
185+
.. doxygenenum:: LIEF::MachO::SYMBOL_DESCRIPTIONS
186+
:project: lief
187+
188+
.. doxygenenum:: LIEF::MachO::X86_RELOCATION
189+
:project: lief
190+
191+
.. doxygenenum:: LIEF::MachO::X86_64_RELOCATION
192+
:project: lief
193+
194+
.. doxygenenum:: LIEF::MachO::PPC_RELOCATION
195+
:project: lief
196+
197+
.. doxygenenum:: LIEF::MachO::ARM_RELOCATION
198+
:project: lief
199+
200+
.. doxygenenum:: LIEF::MachO::ARM64_RELOCATION
201+
:project: lief
202+
203+
.. doxygenenum:: LIEF::MachO::CPU_TYPES
204+
:project: lief
205+
206+
.. doxygenenum:: LIEF::MachO::CPU_SUBTYPES_X86
207+
:project: lief

0 commit comments

Comments
 (0)