Merge pull request #128 from 0xbf00/master

Parse the MachO LC_RPATH command
This commit is contained in:
Romain 2017-12-17 13:55:06 -05:00 committed by GitHub
commit 09f4a4019c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 242 additions and 1 deletions

View File

@ -22,6 +22,7 @@ set(LIEF_PYTHON_MACHO_SRC
"${CMAKE_CURRENT_LIST_DIR}/objects/pyBindingInfo.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyExportInfo.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyThreadCommand.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyRPathCommand.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyParserConfig.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyMachOStructures.cpp"
)

View File

@ -0,0 +1,61 @@
/* Copyright 2017 J.Rieck (based on R. Thomas's work)
* 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/RPathCommand.hpp"
#include "pyMachO.hpp"
template<class T>
using getter_t = T (RPathCommand::*)(void) const;
template<class T>
using setter_t = void (RPathCommand::*)(T);
void init_MachO_RPathCommand_class(py::module& m) {
py::class_<RPathCommand, LoadCommand>(m, "RPathCommand")
.def_property("path",
static_cast<getter_t<const std::string&>>(&RPathCommand::path),
static_cast<setter_t<const std::string&>>(&RPathCommand::path),
"@rpath path",
py::return_value_policy::reference_internal)
.def("__eq__", &RPathCommand::operator==)
.def("__ne__", &RPathCommand::operator!=)
.def("__hash__",
[] (const RPathCommand& rpath_command) {
return LIEF::Hash::hash(rpath_command);
})
.def("__str__",
[] (const RPathCommand& rpath_command)
{
std::ostringstream stream;
stream << rpath_command;
std::string str = stream.str();
return str;
});
}

View File

@ -47,7 +47,7 @@ void init_MachO_module(py::module& m) {
init_MachO_BindingInfo_class(LIEF_MachO_module);
init_MachO_ExportInfo_class(LIEF_MachO_module);
init_MachO_ThreadCommand_class(LIEF_MachO_module);
init_MachO_RPathCommand_class(LIEF_MachO_module);
// Enums
init_MachO_Structures_enum(LIEF_MachO_module);

View File

@ -49,6 +49,7 @@ void init_MachO_RelocationDyld_class(py::module&);
void init_MachO_BindingInfo_class(py::module&);
void init_MachO_ExportInfo_class(py::module&);
void init_MachO_ThreadCommand_class(py::module&);
void init_MachO_RPathCommand_class(py::module&);
// Enums
void init_MachO_Structures_enum(py::module&);

View File

@ -217,6 +217,14 @@ Thread Command
----------
RPath Command
*************
.. doxygenclass:: LIEF::MachO::RPathCommand
:project: lief
----------
Utilities
*********

View File

@ -251,6 +251,17 @@ Thread Command
----------
RPath Command
*************
.. autoclass:: lief.MachO.RPathCommand
:members:
:inherited-members:
:undoc-members:
----------
Enums
*****

View File

@ -40,6 +40,7 @@
#include "LIEF/MachO/SourceVersion.hpp"
#include "LIEF/MachO/VersionMin.hpp"
#include "LIEF/MachO/ThreadCommand.hpp"
#include "LIEF/MachO/RPathCommand.hpp"
namespace LIEF {
namespace MachO {

View File

@ -0,0 +1,55 @@
/* Copyright 2017 J. Rieck (based on R. Thomas's work)
* 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.
*/
#ifndef LIEF_MACHO_RPATH_COMMAND_H_
#define LIEF_MACHO_RPATH_COMMAND_H_
#include <string>
#include <iostream>
#include "LIEF/visibility.h"
#include "LIEF/types.hpp"
#include "LIEF/MachO/LoadCommand.hpp"
namespace LIEF {
namespace MachO {
class DLL_PUBLIC RPathCommand : public LoadCommand {
public:
RPathCommand(void);
RPathCommand(const rpath_command *rpathCmd);
RPathCommand& operator=(const RPathCommand& copy);
RPathCommand(const RPathCommand& copy);
virtual ~RPathCommand(void);
const std::string& path(void) const;
void path(const std::string& path);
bool operator==(const RPathCommand& rhs) const;
bool operator!=(const RPathCommand& rhs) const;
virtual void accept(Visitor& visitor) const override;
virtual std::ostream& print(std::ostream& os) const override;
private:
std::string path_;
};
}
}
#endif

View File

@ -146,6 +146,7 @@ class DynamicSymbolCommand;
class DylinkerCommand;
class DylibCommand;
class ThreadCommand;
class RPathCommand;
class Symbol;
class Relocation;
@ -481,6 +482,9 @@ class DLL_PUBLIC Visitor {
//! @brief Method to visit a LIEF::MachO::ThreadCommand
virtual void visit(const MachO::ThreadCommand& thread);
//! @brief Method to visit a LIEF::MachO::RPathCommand
virtual void visit(const MachO::RPathCommand& rpath_command);
#endif
template<class T>

View File

@ -158,6 +158,23 @@ void BinaryParser::parse_load_commands(void) {
break;
}
// =============
// RPath Command
// =============
case LOAD_COMMAND_TYPES::LC_RPATH:
{
const rpath_command* cmd =
reinterpret_cast<const rpath_command*>(
this->stream_->read(loadcommands_offset, sizeof(rpath_command)));
load_command = std::unique_ptr<RPathCommand>{new RPathCommand{cmd}};
const uint32_t str_path_offset = cmd->path;
std::string path = this->stream_->get_string(loadcommands_offset + str_path_offset);
dynamic_cast<RPathCommand*>(load_command.get())->path(path);
break;
}
// ====
// UUID
// ====

View File

@ -45,6 +45,7 @@ set(LIEF_MACHO_SRC
"${CMAKE_CURRENT_LIST_DIR}/BindingInfo.cpp"
"${CMAKE_CURRENT_LIST_DIR}/ExportInfo.cpp"
"${CMAKE_CURRENT_LIST_DIR}/ThreadCommand.cpp"
"${CMAKE_CURRENT_LIST_DIR}/RPathCommand.cpp"
"${CMAKE_CURRENT_LIST_DIR}/ParserConfig.cpp"
"${CMAKE_CURRENT_LIST_DIR}/Visitor.cpp"
)
@ -79,6 +80,7 @@ set(LIEF_MACHO_INCLUDE_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/RelocationDyld.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/BindingInfo.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/ExportInfo.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/RPathCommand.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/ThreadCommand.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/ParserConfig.hpp"
)

View File

@ -0,0 +1,71 @@
/* Copyright 2017 J.Rieck (based on R. Thomas's work)
* 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 <numeric>
#include <iomanip>
#include "LIEF/visitors/Hash.hpp"
#include "LIEF/MachO/RPathCommand.hpp"
namespace LIEF {
namespace MachO {
RPathCommand::RPathCommand(void) = default;
RPathCommand& RPathCommand::operator=(const RPathCommand&) = default;
RPathCommand::RPathCommand(const RPathCommand&) = default;
RPathCommand::~RPathCommand(void) = default;
RPathCommand::RPathCommand(const rpath_command *rpathCmd) :
LoadCommand::LoadCommand{static_cast<LOAD_COMMAND_TYPES>(rpathCmd->cmd), rpathCmd->cmdsize}
{
}
const std::string& RPathCommand::path(void) const {
return this->path_;
}
void RPathCommand::path(const std::string& path) {
this->path_ = path;
}
void RPathCommand::accept(Visitor& visitor) const {
LoadCommand::accept(visitor);
visitor.visit(this->path());
}
bool RPathCommand::operator==(const RPathCommand& rhs) const {
size_t hash_lhs = Hash::hash(*this);
size_t hash_rhs = Hash::hash(rhs);
return hash_lhs == hash_rhs;
}
bool RPathCommand::operator!=(const RPathCommand& rhs) const {
return not (*this == rhs);
}
std::ostream& RPathCommand::print(std::ostream& os) const {
LoadCommand::print(os);
os << std::left
<< std::setw(10) << "Path: " << this->path();
return os;
}
}
}

View File

@ -93,4 +93,8 @@ void Visitor::visit(const MachO::ThreadCommand& thread) {
thread.accept(*this);
}
void Visitor::visit(const MachO::RPathCommand& rpath_command) {
rpath_command.accept(*this);
}
}

View File

@ -62,6 +62,11 @@ class TestMachO(TestCase):
self.assertEqual(micromacho.thread_command.count, 16)
self.assertEqual(micromacho.entrypoint, 0x68)
def test_rpath_cmd(self):
rpathmacho = lief.parse(get_sample('MachO/MachO64_x86-64_binary_rpathtest.bin'))
load_cmds = list(rpathmacho.commands)
rpath_cmd = load_cmds[-3]
self.assertEqual(rpath_cmd.path, "@executable_path/../lib")
def test_relocations(self):
helloworld = lief.parse(get_sample('MachO/MachO64_x86-64_object_HelloWorld64.o'))