Skip to content

Commit 196994d

Browse files
committed
Parse the MachO LC_RPATH command
1 parent 23d4e82 commit 196994d

File tree

13 files changed

+237
-1
lines changed

13 files changed

+237
-1
lines changed

api/python/MachO/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ set(LIEF_PYTHON_MACHO_SRC
2222
"${CMAKE_CURRENT_LIST_DIR}/objects/pyBindingInfo.cpp"
2323
"${CMAKE_CURRENT_LIST_DIR}/objects/pyExportInfo.cpp"
2424
"${CMAKE_CURRENT_LIST_DIR}/objects/pyThreadCommand.cpp"
25+
"${CMAKE_CURRENT_LIST_DIR}/objects/pyRPathCommand.cpp"
2526
"${CMAKE_CURRENT_LIST_DIR}/objects/pyParserConfig.cpp"
2627
"${CMAKE_CURRENT_LIST_DIR}/pyMachOStructures.cpp"
2728
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/* Copyright 2017 J.Rieck (based on R. Thomas's work)
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/RPathCommand.hpp"
23+
24+
#include "pyMachO.hpp"
25+
26+
template<class T>
27+
using getter_t = T (RPathCommand::*)(void) const;
28+
29+
template<class T>
30+
using setter_t = void (RPathCommand::*)(T);
31+
32+
33+
void init_MachO_RPathCommand_class(py::module& m) {
34+
35+
py::class_<RPathCommand, LoadCommand>(m, "RPathCommand")
36+
37+
.def_property("path",
38+
static_cast<getter_t<const std::string&>>(&RPathCommand::path),
39+
static_cast<setter_t<const std::string&>>(&RPathCommand::path),
40+
"@rpath path",
41+
py::return_value_policy::reference_internal)
42+
43+
44+
.def("__eq__", &RPathCommand::operator==)
45+
.def("__ne__", &RPathCommand::operator!=)
46+
.def("__hash__",
47+
[] (const RPathCommand& rpath_command) {
48+
return LIEF::Hash::hash(rpath_command);
49+
})
50+
51+
52+
.def("__str__",
53+
[] (const RPathCommand& rpath_command)
54+
{
55+
std::ostringstream stream;
56+
stream << rpath_command;
57+
std::string str = stream.str();
58+
return str;
59+
});
60+
61+
}

api/python/MachO/pyMachO.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ void init_MachO_module(py::module& m) {
4747
init_MachO_BindingInfo_class(LIEF_MachO_module);
4848
init_MachO_ExportInfo_class(LIEF_MachO_module);
4949
init_MachO_ThreadCommand_class(LIEF_MachO_module);
50-
50+
init_MachO_RPathCommand_class(LIEF_MachO_module);
5151

5252
// Enums
5353
init_MachO_Structures_enum(LIEF_MachO_module);

api/python/MachO/pyMachO.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ void init_MachO_RelocationDyld_class(py::module&);
4949
void init_MachO_BindingInfo_class(py::module&);
5050
void init_MachO_ExportInfo_class(py::module&);
5151
void init_MachO_ThreadCommand_class(py::module&);
52+
void init_MachO_RPathCommand_class(py::module&);
5253

5354
// Enums
5455
void init_MachO_Structures_enum(py::module&);

doc/sphinx/api/cpp/macho.rst

+8
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,14 @@ Thread Command
217217

218218
----------
219219

220+
RPath Command
221+
*************
222+
223+
.. doxygenclass:: LIEF::MachO::RPathCommand
224+
:project: lief
225+
226+
----------
227+
220228
Utilities
221229
*********
222230

doc/sphinx/api/python/macho.rst

+11
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,17 @@ Thread Command
251251

252252
----------
253253

254+
RPath Command
255+
*************
256+
257+
.. autoclass:: lief.MachO.RPathCommand
258+
:members:
259+
:inherited-members:
260+
:undoc-members:
261+
262+
----------
263+
264+
254265
Enums
255266
*****
256267

include/LIEF/MachO/Binary.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "LIEF/MachO/SourceVersion.hpp"
4141
#include "LIEF/MachO/VersionMin.hpp"
4242
#include "LIEF/MachO/ThreadCommand.hpp"
43+
#include "LIEF/MachO/RPathCommand.hpp"
4344

4445
namespace LIEF {
4546
namespace MachO {

include/LIEF/MachO/RPathCommand.hpp

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/* Copyright 2017 J. Rieck (based on R. Thomas's work)
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+
#ifndef LIEF_MACHO_RPATH_COMMAND_H_
17+
#define LIEF_MACHO_RPATH_COMMAND_H_
18+
#include <string>
19+
#include <iostream>
20+
21+
#include "LIEF/visibility.h"
22+
#include "LIEF/types.hpp"
23+
24+
#include "LIEF/MachO/LoadCommand.hpp"
25+
26+
namespace LIEF {
27+
namespace MachO {
28+
29+
class DLL_PUBLIC RPathCommand : public LoadCommand {
30+
public:
31+
RPathCommand(void);
32+
RPathCommand(const rpath_command *rpathCmd);
33+
34+
RPathCommand& operator=(const RPathCommand& copy);
35+
RPathCommand(const RPathCommand& copy);
36+
37+
virtual ~RPathCommand(void);
38+
39+
const std::string& path(void) const;
40+
void path(const std::string& path);
41+
42+
bool operator==(const RPathCommand& rhs) const;
43+
bool operator!=(const RPathCommand& rhs) const;
44+
45+
virtual void accept(Visitor& visitor) const override;
46+
47+
virtual std::ostream& print(std::ostream& os) const override;
48+
49+
private:
50+
std::string path_;
51+
};
52+
53+
}
54+
}
55+
#endif

include/LIEF/Visitor.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ class DynamicSymbolCommand;
146146
class DylinkerCommand;
147147
class DylibCommand;
148148
class ThreadCommand;
149+
class RPathCommand;
149150

150151
class Symbol;
151152
class Relocation;
@@ -481,6 +482,9 @@ class DLL_PUBLIC Visitor {
481482

482483
//! @brief Method to visit a LIEF::MachO::ThreadCommand
483484
virtual void visit(const MachO::ThreadCommand& thread);
485+
486+
//! @brief Method to visit a LIEF::MachO::RPathCommand
487+
virtual void visit(const MachO::RPathCommand& rpath_command);
484488
#endif
485489

486490
template<class T>

src/MachO/BinaryParser.tcc

+17
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,23 @@ void BinaryParser::parse_load_commands(void) {
158158
break;
159159
}
160160

161+
// =============
162+
// RPath Command
163+
// =============
164+
case LOAD_COMMAND_TYPES::LC_RPATH:
165+
{
166+
const rpath_command* cmd =
167+
reinterpret_cast<const rpath_command*>(
168+
this->stream_->read(loadcommands_offset, sizeof(rpath_command)));
169+
170+
load_command = std::unique_ptr<RPathCommand>{new RPathCommand{cmd}};
171+
const uint32_t str_path_offset = cmd->path;
172+
std::string path = this->stream_->get_string(loadcommands_offset + str_path_offset);
173+
174+
dynamic_cast<RPathCommand*>(load_command.get())->path(path);
175+
break;
176+
}
177+
161178
// ====
162179
// UUID
163180
// ====

src/MachO/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ set(LIEF_MACHO_SRC
4545
"${CMAKE_CURRENT_LIST_DIR}/BindingInfo.cpp"
4646
"${CMAKE_CURRENT_LIST_DIR}/ExportInfo.cpp"
4747
"${CMAKE_CURRENT_LIST_DIR}/ThreadCommand.cpp"
48+
"${CMAKE_CURRENT_LIST_DIR}/RPathCommand.cpp"
4849
"${CMAKE_CURRENT_LIST_DIR}/ParserConfig.cpp"
4950
"${CMAKE_CURRENT_LIST_DIR}/Visitor.cpp"
5051
)
@@ -79,6 +80,7 @@ set(LIEF_MACHO_INCLUDE_FILES
7980
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/RelocationDyld.hpp"
8081
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/BindingInfo.hpp"
8182
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/ExportInfo.hpp"
83+
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/RPathCommand.hpp"
8284
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/ThreadCommand.hpp"
8385
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/ParserConfig.hpp"
8486
)

src/MachO/RPathCommand.cpp

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/* Copyright 2017 J.Rieck (based on R. Thomas's work)
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 <numeric>
17+
#include <iomanip>
18+
19+
#include "LIEF/visitors/Hash.hpp"
20+
21+
#include "LIEF/MachO/RPathCommand.hpp"
22+
23+
namespace LIEF {
24+
namespace MachO {
25+
26+
RPathCommand::RPathCommand(void) = default;
27+
RPathCommand& RPathCommand::operator=(const RPathCommand&) = default;
28+
RPathCommand::RPathCommand(const RPathCommand&) = default;
29+
RPathCommand::~RPathCommand(void) = default;
30+
31+
RPathCommand::RPathCommand(const rpath_command *rpathCmd) :
32+
LoadCommand::LoadCommand{static_cast<LOAD_COMMAND_TYPES>(rpathCmd->cmd), rpathCmd->cmdsize}
33+
{
34+
}
35+
36+
const std::string& RPathCommand::path(void) const {
37+
return this->path_;
38+
}
39+
40+
void RPathCommand::path(const std::string& path) {
41+
this->path_ = path;
42+
}
43+
44+
45+
void RPathCommand::accept(Visitor& visitor) const {
46+
LoadCommand::accept(visitor);
47+
visitor.visit(this->path());
48+
}
49+
50+
51+
bool RPathCommand::operator==(const RPathCommand& rhs) const {
52+
size_t hash_lhs = Hash::hash(*this);
53+
size_t hash_rhs = Hash::hash(rhs);
54+
return hash_lhs == hash_rhs;
55+
}
56+
57+
bool RPathCommand::operator!=(const RPathCommand& rhs) const {
58+
return not (*this == rhs);
59+
}
60+
61+
62+
std::ostream& RPathCommand::print(std::ostream& os) const {
63+
LoadCommand::print(os);
64+
os << std::left
65+
<< std::setw(10) << "Path: " << this->path();
66+
return os;
67+
}
68+
69+
70+
}
71+
}

src/MachO/Visitor.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,8 @@ void Visitor::visit(const MachO::ThreadCommand& thread) {
9393
thread.accept(*this);
9494
}
9595

96+
void Visitor::visit(const MachO::RPathCommand& rpath_command) {
97+
rpath_command.accept(*this);
98+
}
99+
96100
}

0 commit comments

Comments
 (0)