Skip to content

Commit 782295b

Browse files
committed
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
1 parent 8d25408 commit 782295b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+3791
-311
lines changed

api/python/MachO/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ set(LIEF_PYTHON_MACHO_SRC
1616
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDyldInfo.cpp"
1717
"${CMAKE_CURRENT_LIST_DIR}/objects/pyFunctionStarts.cpp"
1818
"${CMAKE_CURRENT_LIST_DIR}/objects/pyRelocation.cpp"
19+
"${CMAKE_CURRENT_LIST_DIR}/objects/pyRelocationObject.cpp"
20+
"${CMAKE_CURRENT_LIST_DIR}/objects/pyRelocationDyld.cpp"
21+
"${CMAKE_CURRENT_LIST_DIR}/objects/pyBindingInfo.cpp"
22+
"${CMAKE_CURRENT_LIST_DIR}/objects/pyExportInfo.cpp"
1923
"${CMAKE_CURRENT_LIST_DIR}/pyMachOStructures.cpp"
2024
)
2125

api/python/MachO/objects/pyBinary.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
template<class T>
2424
using no_const_getter = T (Binary::*)(void);
2525

26+
template<class T, class P>
27+
using no_const_func = T (Binary::*)(P);
28+
2629
void init_MachO_Binary_class(py::module& m) {
2730

2831

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

43+
.def_property_readonly("relocations",
44+
static_cast<no_const_getter<it_relocations>>(&Binary::relocations),
45+
"Return an iterator over binary's " RST_CLASS_REF(lief.MachO.Relocation) "",
46+
py::return_value_policy::reference_internal)
47+
4048
.def_property_readonly("segments",
4149
static_cast<no_const_getter<it_segments>>(&Binary::segments),
4250
"Return binary's " RST_CLASS_REF(lief.MachO.SegmentCommand) "",
@@ -52,6 +60,17 @@ void init_MachO_Binary_class(py::module& m) {
5260
"Return binary's " RST_CLASS_REF(lief.MachO.Symbol) "",
5361
py::return_value_policy::reference_internal)
5462

63+
.def("has_symbol",
64+
&Binary::has_symbol,
65+
"Check if a " RST_CLASS_REF(lief.MachO.Symbol) " with the given name exists",
66+
"name"_a)
67+
68+
.def("get_symbol",
69+
static_cast<no_const_func<Symbol&, const std::string&>>(&Binary::get_symbol),
70+
"Return the " RST_CLASS_REF(lief.MachO.Symbol) " from the given name",
71+
"name"_a,
72+
py::return_value_policy::reference)
73+
5574
.def_property_readonly("imported_symbols",
5675
static_cast<no_const_getter<it_imported_symbols>>(&Binary::get_imported_symbols),
5776
"Return binary's " RST_CLASS_REF(lief.MachO.Symbol) " which are imported",
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
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/BindingInfo.hpp"
23+
24+
#include "pyMachO.hpp"
25+
26+
template<class T>
27+
using getter_t = T (BindingInfo::*)(void) const;
28+
29+
template<class T>
30+
using setter_t = void (BindingInfo::*)(T);
31+
32+
33+
void init_MachO_BindingInfo_class(py::module& m) {
34+
35+
py::class_<BindingInfo>(m, "BindingInfo")
36+
37+
.def_property("binding_class",
38+
static_cast<getter_t<BINDING_CLASS>>(&BindingInfo::binding_class),
39+
static_cast<setter_t<BINDING_CLASS>>(&BindingInfo::binding_class),
40+
"" RST_CLASS_REF(lief.MachO.BINDING_CLASS) " of the binding",
41+
py::return_value_policy::reference_internal)
42+
43+
.def_property("address",
44+
static_cast<getter_t<uint64_t>>(&BindingInfo::address),
45+
static_cast<setter_t<uint64_t>>(&BindingInfo::address),
46+
"Binding's address",
47+
py::return_value_policy::reference_internal)
48+
49+
.def_property("binding_type",
50+
static_cast<getter_t<BIND_TYPES>>(&BindingInfo::binding_type),
51+
static_cast<setter_t<BIND_TYPES>>(&BindingInfo::binding_type),
52+
"" RST_CLASS_REF(lief.MachO.BIND_TYPES) " of the binding\n"
53+
"Most of the times it's :attr:`~lief.MachO.BIND_TYPES.POINTER`",
54+
py::return_value_policy::reference_internal)
55+
56+
57+
.def_property("library_ordinal",
58+
static_cast<getter_t<int32_t>>(&BindingInfo::library_ordinal),
59+
static_cast<setter_t<int32_t>>(&BindingInfo::library_ordinal),
60+
py::return_value_policy::reference_internal)
61+
62+
.def_property("addend",
63+
static_cast<getter_t<int64_t>>(&BindingInfo::addend),
64+
static_cast<setter_t<int64_t>>(&BindingInfo::addend),
65+
"Value added to the segment's virtual address when binding",
66+
py::return_value_policy::reference_internal)
67+
68+
.def_property("weak_import",
69+
static_cast<getter_t<bool>>(&BindingInfo::is_weak_import),
70+
static_cast<setter_t<bool>>(&BindingInfo::set_weak_import),
71+
py::return_value_policy::reference_internal)
72+
73+
74+
.def_property_readonly("has_library",
75+
&BindingInfo::has_library,
76+
"``True`` if the binding info has a " RST_CLASS_REF(lief.MachO.DylibCommand) " associated with")
77+
78+
.def_property_readonly("library",
79+
static_cast<DylibCommand& (BindingInfo::*)(void)>(&BindingInfo::library),
80+
"" RST_CLASS_REF(lief.MachO.DylibCommand) " associated with the binding (if any)",
81+
py::return_value_policy::reference)
82+
83+
84+
.def_property_readonly("has_segment",
85+
&BindingInfo::has_segment,
86+
"``True`` if the binding info has a " RST_CLASS_REF(lief.MachO.SegmentCommand) " associated with")
87+
88+
.def_property_readonly("segment",
89+
static_cast<SegmentCommand& (BindingInfo::*)(void)>(&BindingInfo::segment),
90+
"" RST_CLASS_REF(lief.MachO.SegmentCommand) " associated with the binding (if any)",
91+
py::return_value_policy::reference)
92+
93+
94+
.def_property_readonly("has_symbol",
95+
&BindingInfo::has_symbol,
96+
"``True`` if the binding info has a " RST_CLASS_REF(lief.MachO.Symbol) " associated with")
97+
98+
.def_property_readonly("symbol",
99+
static_cast<Symbol& (BindingInfo::*)(void)>(&BindingInfo::symbol),
100+
"" RST_CLASS_REF(lief.MachO.Symbol) " associated with the binding (if any)",
101+
py::return_value_policy::reference)
102+
103+
104+
.def("__eq__", &BindingInfo::operator==)
105+
.def("__ne__", &BindingInfo::operator!=)
106+
.def("__hash__",
107+
[] (const BindingInfo& binding_info) {
108+
return LIEF::Hash::hash(binding_info);
109+
})
110+
111+
112+
.def("__str__",
113+
[] (const BindingInfo& binding_info)
114+
{
115+
std::ostringstream stream;
116+
stream << binding_info;
117+
std::string str = stream.str();
118+
return str;
119+
});
120+
121+
}

api/python/MachO/objects/pyDyldInfo.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ using getter_t = T (DyldInfo::*)(void) const;
2929
template<class T>
3030
using setter_t = void (DyldInfo::*)(T);
3131

32+
template<class T>
33+
using no_const_getter = T (DyldInfo::*)(void);
3234

3335
void init_MachO_DyldInfo_class(py::module& m) {
3436

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

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

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

7783

84+
.def_property("bind_opcodes",
85+
static_cast<getter_t<const buffer_t&>>(&DyldInfo::bind_opcodes),
86+
static_cast<setter_t<const buffer_t&>>(&DyldInfo::bind_opcodes),
87+
"Return Binding's opcodes as ``list`` of bytes")
88+
89+
7890
.def_property("weak_bind",
7991
static_cast<getter_t<const LIEF::MachO::DyldInfo::info_t&>>(&DyldInfo::weak_bind),
8092
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) {
99111
py::return_value_policy::reference_internal)
100112

101113

114+
.def_property("weak_bind_opcodes",
115+
static_cast<getter_t<const buffer_t&>>(&DyldInfo::weak_bind_opcodes),
116+
static_cast<setter_t<const buffer_t&>>(&DyldInfo::weak_bind_opcodes),
117+
"Return **Weak** binding's opcodes as ``list`` of bytes")
118+
119+
102120
.def_property("lazy_bind",
103121
static_cast<getter_t<const LIEF::MachO::DyldInfo::info_t&>>(&DyldInfo::lazy_bind),
104122
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) {
120138
py::return_value_policy::reference_internal)
121139

122140

141+
.def_property("lazy_bind_opcodes",
142+
static_cast<getter_t<const buffer_t&>>(&DyldInfo::lazy_bind_opcodes),
143+
static_cast<setter_t<const buffer_t&>>(&DyldInfo::lazy_bind_opcodes),
144+
"Return **lazy** binding's opcodes as ``list`` of bytes")
145+
146+
.def_property_readonly("bindings",
147+
static_cast<no_const_getter<it_binding_info>>(&DyldInfo::bindings),
148+
"Return an iterator over Dyld's " RST_CLASS_REF(lief.MachO.BindingInfo) "",
149+
py::return_value_policy::reference_internal)
150+
123151
.def_property("export_info",
124152
static_cast<getter_t<const LIEF::MachO::DyldInfo::info_t&>>(&DyldInfo::export_info),
125153
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) {
152180
"\t``/usr/include/mach-o/loader.h``\n",
153181
py::return_value_policy::reference_internal)
154182

183+
.def_property("export_trie",
184+
static_cast<getter_t<const buffer_t&>>(&DyldInfo::export_trie),
185+
static_cast<setter_t<const buffer_t&>>(&DyldInfo::export_trie),
186+
"Return Export's trie as ``list`` of bytes")
187+
188+
.def_property_readonly("exports",
189+
static_cast<no_const_getter<it_export_info>>(&DyldInfo::exports),
190+
"Return an iterator over Dyld's " RST_CLASS_REF(lief.MachO.ExportInfo) "",
191+
py::return_value_policy::reference_internal)
192+
155193
.def("set_rebase_offset",
156194
&DyldInfo::set_rebase_offset,
157195
"offset"_a)
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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/ExportInfo.hpp"
23+
24+
#include "pyMachO.hpp"
25+
26+
template<class T>
27+
using getter_t = T (ExportInfo::*)(void) const;
28+
29+
template<class T>
30+
using setter_t = void (ExportInfo::*)(T);
31+
32+
33+
void init_MachO_ExportInfo_class(py::module& m) {
34+
35+
py::class_<ExportInfo>(m, "ExportInfo")
36+
37+
.def_property_readonly("node_offset",
38+
static_cast<getter_t<uint64_t>>(&ExportInfo::node_offset))
39+
40+
.def_property("flags",
41+
static_cast<getter_t<uint64_t>>(&ExportInfo::flags),
42+
static_cast<setter_t<uint64_t>>(&ExportInfo::flags),
43+
py::return_value_policy::reference_internal)
44+
45+
.def_property("address",
46+
static_cast<getter_t<uint64_t>>(&ExportInfo::address),
47+
static_cast<setter_t<uint64_t>>(&ExportInfo::address),
48+
py::return_value_policy::reference_internal)
49+
50+
.def_property_readonly("has_symbol",
51+
&ExportInfo::has_symbol,
52+
"``True`` if the export info has a " RST_CLASS_REF(lief.MachO.Symbol) " associated with")
53+
54+
.def_property_readonly("symbol",
55+
static_cast<Symbol& (ExportInfo::*)(void)>(&ExportInfo::symbol),
56+
"" RST_CLASS_REF(lief.MachO.Symbol) " associated with the export (if any)",
57+
py::return_value_policy::reference)
58+
59+
60+
.def("__eq__", &ExportInfo::operator==)
61+
.def("__ne__", &ExportInfo::operator!=)
62+
.def("__hash__",
63+
[] (const ExportInfo& export_info) {
64+
return LIEF::Hash::hash(export_info);
65+
})
66+
67+
68+
.def("__str__",
69+
[] (const ExportInfo& export_info)
70+
{
71+
std::ostringstream stream;
72+
stream << export_info;
73+
std::string str = stream.str();
74+
return str;
75+
});
76+
77+
}

0 commit comments

Comments
 (0)