Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Provide MachO::ParserConfig to parametrize the parsing.
Resolve: #105
  • Loading branch information
romainthomas committed Oct 30, 2017
1 parent c61caae commit 880b99a
Show file tree
Hide file tree
Showing 16 changed files with 232 additions and 30 deletions.
1 change: 1 addition & 0 deletions api/python/MachO/CMakeLists.txt
Expand Up @@ -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/pyParserConfig.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyMachOStructures.cpp"
)

Expand Down
17 changes: 12 additions & 5 deletions api/python/MachO/objects/pyParser.cpp
Expand Up @@ -24,16 +24,23 @@ void init_MachO_Parser_class(py::module& m) {

// Parser (Parser)
m.def("parse",
static_cast<FatBinary* (*) (const std::string&)>(&LIEF::MachO::Parser::parse),
"Parse the given binary and return a **list** of " RST_CLASS_REF(lief.MachO.Binary) " objects",
static_cast<FatBinary* (*) (const std::string&, const ParserConfig&)>(&LIEF::MachO::Parser::parse),
"Parse the given binary and return a " RST_CLASS_REF(lief.MachO.FatBinary) " object\n\n"

"One can configure the parsing with the ``config`` parameter. See " RST_CLASS_REF(lief.MachO.ParserConfig) "",
"filename"_a,
"config"_a = ParserConfig::deep(),
py::return_value_policy::take_ownership);


m.def("parse",
static_cast<FatBinary* (*) (const std::vector<uint8_t>&, const std::string&)>(&LIEF::MachO::Parser::parse),
"Parse the given binary (from raw) and return a **list** of " RST_CLASS_REF(lief.MachO.Binary) " objects",
py::arg("raw"), py::arg("name") = "",
static_cast<FatBinary* (*) (const std::vector<uint8_t>&, const std::string&, const ParserConfig&)>(&LIEF::MachO::Parser::parse),
"Parse the given binary (from raw) and return a " RST_CLASS_REF(lief.MachO.FatBinary) " objects\n\n"

"One can configure the parsing with the ``config`` parameter. See " RST_CLASS_REF(lief.MachO.ParserConfig) "",
"raw"_a,
"name"_a = "",
"config"_a = ParserConfig::quick(),
py::return_value_policy::take_ownership);


Expand Down
46 changes: 46 additions & 0 deletions api/python/MachO/objects/pyParserConfig.cpp
@@ -0,0 +1,46 @@
/* 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 <string>

#include "LIEF/MachO/ParserConfig.hpp"

#include "pyMachO.hpp"

void init_MachO_ParserConfig_class(py::module& m) {

py::class_<ParserConfig>(m, "ParserConfig", "Configuration of MachO's parser")
.def(py::init<>())
.def_property("parse_dyldinfo_deeply",
static_cast<bool (ParserConfig::*)(void) const>(&ParserConfig::parse_dyldinfo_deeply),
static_cast<ParserConfig& (ParserConfig::*)(bool)>(&ParserConfig::parse_dyldinfo_deeply),
"If set to ``True``, parse deeply the " RST_CLASS_REF(lief.MachO.DyldInfo) " "
"structure. It includes Exports, Bindings and Rebases")

.def_property_readonly_static("deep",
[] (py::object /* self */) { return ParserConfig::deep(); },
"foobar")

.def_property_readonly_static("quick",
[] (py::object /* self */) { return ParserConfig::quick(); },
"");







}
1 change: 1 addition & 0 deletions api/python/MachO/pyMachO.cpp
Expand Up @@ -24,6 +24,7 @@ void init_MachO_module(py::module& m) {
py::module LIEF_MachO_module = m.def_submodule("MachO", "Python API for MachO");

// Objects
init_MachO_ParserConfig_class(LIEF_MachO_module);
init_MachO_Parser_class(LIEF_MachO_module);
init_MachO_FatBinary_class(LIEF_MachO_module);
init_MachO_Binary_class(LIEF_MachO_module);
Expand Down
1 change: 1 addition & 0 deletions api/python/MachO/pyMachO.hpp
Expand Up @@ -26,6 +26,7 @@ using namespace LIEF::MachO;

PYBIND11_MAKE_OPAQUE(std::vector<Binary*>)

void init_MachO_ParserConfig_class(py::module&);
void init_MachO_Parser_class(py::module&);
void init_MachO_FatBinary_class(py::module&);
void init_MachO_Binary_class(py::module&);
Expand Down
1 change: 1 addition & 0 deletions api/python/pyLIEF.hpp
Expand Up @@ -28,6 +28,7 @@
#include "pyIterators.hpp"

#define RST_CLASS_REF(X) ":class:`~"#X"`"
#define RST_ATTR_REF(X) ":attr:`~"#X"`"

namespace py = pybind11;

Expand Down
4 changes: 4 additions & 0 deletions doc/sphinx/api/cpp/macho.rst
Expand Up @@ -11,6 +11,10 @@ Parsers
.. doxygenclass:: LIEF::MachO::BinaryParser
:project: lief


.. doxygenclass:: LIEF::MachO::ParserConfig
:project: lief

----------

FatBinary
Expand Down
13 changes: 12 additions & 1 deletion doc/sphinx/api/python/macho.rst
Expand Up @@ -7,9 +7,21 @@ Parser

.. autofunction:: lief.MachO.parse

.. autoclass:: lief.MachO.ParserConfig
:members:
:inherited-members:
:undoc-members:

.. code-block:: python
fatbinary_1 = lief.MachO.parse("/usr/bin/ls", config=lief.MachO.ParserConfig.deep)
# or
fatbinary_2 = lief.MachO.parse("/usr/bin/ls", config=lief.MachO.ParserConfig.quick)
----------


FatBinary
*********

Expand Down Expand Up @@ -239,7 +251,6 @@ Thread Command

----------


Enums
*****

Expand Down
8 changes: 5 additions & 3 deletions include/LIEF/MachO/BinaryParser.hpp
Expand Up @@ -26,6 +26,7 @@

#include "LIEF/Abstract/Parser.hpp"

#include "LIEF/MachO/ParserConfig.hpp"
#include "LIEF/MachO/Structures.hpp"
#include "LIEF/MachO/Binary.hpp"
#include "LIEF/MachO/LoadCommand.hpp"
Expand All @@ -47,8 +48,8 @@ class DLL_PUBLIC BinaryParser : public LIEF::Parser {
constexpr static size_t MAX_COMMANDS = std::numeric_limits<uint8_t>::max();

public:
BinaryParser(const std::string& file);
BinaryParser(const std::vector<uint8_t>& data, uint64_t fat_offset = 0);
BinaryParser(const std::string& file, const ParserConfig& conf = ParserConfig::deep());
BinaryParser(const std::vector<uint8_t>& data, uint64_t fat_offset = 0, const ParserConfig& conf = ParserConfig::deep());
BinaryParser(void);

BinaryParser& operator=(const BinaryParser& copy) = delete;
Expand All @@ -59,7 +60,7 @@ class DLL_PUBLIC BinaryParser : public LIEF::Parser {
Binary* get_binary(void);

private:
BinaryParser(std::unique_ptr<VectorStream>&& stream, uint64_t fat_offset = 0);
BinaryParser(std::unique_ptr<VectorStream>&& stream, uint64_t fat_offset = 0, const ParserConfig& conf = ParserConfig::deep());

void init(void);

Expand Down Expand Up @@ -122,6 +123,7 @@ class DLL_PUBLIC BinaryParser : public LIEF::Parser {
Binary* binary_ ;
MACHO_TYPES type_;
bool is64_;
ParserConfig config_;
};


Expand Down
10 changes: 6 additions & 4 deletions include/LIEF/MachO/Parser.hpp
Expand Up @@ -24,6 +24,7 @@

#include "LIEF/Abstract/Parser.hpp"

#include "LIEF/MachO/ParserConfig.hpp"
#include "LIEF/MachO/Structures.hpp"
#include "LIEF/MachO/Binary.hpp"
#include "LIEF/MachO/FatBinary.hpp"
Expand All @@ -38,19 +39,20 @@ class DLL_PUBLIC Parser : public LIEF::Parser {

~Parser(void);

static FatBinary* parse(const std::string& filename);
static FatBinary* parse(const std::vector<uint8_t>& data, const std::string& name = "");
static FatBinary* parse(const std::string& filename, const ParserConfig& conf = ParserConfig::deep());
static FatBinary* parse(const std::vector<uint8_t>& data, const std::string& name = "", const ParserConfig& conf = ParserConfig::deep());

private:
Parser(const std::string& file);
Parser(const std::vector<uint8_t>& data, const std::string& name);
Parser(const std::string& file, const ParserConfig& conf);
Parser(const std::vector<uint8_t>& data, const std::string& name, const ParserConfig& conf);
Parser(void);

void build(void);
void build_fat(void);

std::unique_ptr<VectorStream> stream_;
std::vector<Binary*> binaries_;
ParserConfig config_;
};
}
}
Expand Down
59 changes: 59 additions & 0 deletions include/LIEF/MachO/ParserConfig.hpp
@@ -0,0 +1,59 @@
/* 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.
*/
#ifndef LIEF_MACHO_PARSER_CONFIG_H_
#define LIEF_MACHO_PARSER_CONFIG_H_
#include "LIEF/visibility.h"

namespace LIEF {
namespace MachO {

class DLL_PUBLIC ParserConfig {
public:
ParserConfig(void);
ParserConfig& operator=(const ParserConfig&);
ParserConfig(const ParserConfig&);
~ParserConfig(void);

//! @brief Return a configuration so that the all objects supported by
//! LIEF are parsed
//!
//! With this configuration:
//! * ``parse_dyldinfo_deeply`` is set to ``true``
static ParserConfig deep(void);

//! Return a configuration so that the parsing is quick
//!
//! With this configuration:
//! * ``parse_dyldinfo_deeply`` is set to ``false``
static ParserConfig quick(void);

//! @brief If ``flag`` is set to ``true``,
//! Exports, Bindings and Rebases opcodes are
//! parsed.
//!
//! @warning Enabling this flag can slow down the parsing
ParserConfig& parse_dyldinfo_deeply(bool flag);

//! @brief Whether or not bindings, exports, and rebases are parsed
bool parse_dyldinfo_deeply(void) const;

private:
bool dyldinfo_deeply_;
};

}
}
#endif
15 changes: 9 additions & 6 deletions src/MachO/BinaryParser.cpp
Expand Up @@ -45,25 +45,28 @@ namespace MachO {
BinaryParser::BinaryParser(void) = default;
BinaryParser::~BinaryParser(void) = default;

BinaryParser::BinaryParser(const std::vector<uint8_t>& data, uint64_t fat_offset) :
BinaryParser::BinaryParser(const std::vector<uint8_t>& data, uint64_t fat_offset, const ParserConfig& conf) :
stream_{new VectorStream{data}},
binary_{new Binary{}}
binary_{new Binary{}},
config_{conf}
{
this->binary_->fat_offset_ = fat_offset;
this->init();
}


BinaryParser::BinaryParser(std::unique_ptr<VectorStream>&& stream, uint64_t fat_offset) :
BinaryParser::BinaryParser(std::unique_ptr<VectorStream>&& stream, uint64_t fat_offset, const ParserConfig& conf) :
stream_{std::move(stream)},
binary_{new Binary{}}
binary_{new Binary{}},
config_{conf}
{
this->binary_->fat_offset_ = fat_offset;
this->init();
}

BinaryParser::BinaryParser(const std::string& file) :
LIEF::Parser{file}
BinaryParser::BinaryParser(const std::string& file, const ParserConfig& conf) :
LIEF::Parser{file},
config_{conf}
{

if (not is_macho(file)) {
Expand Down
2 changes: 1 addition & 1 deletion src/MachO/BinaryParser.tcc
Expand Up @@ -43,7 +43,7 @@ void BinaryParser::parse(void) {
}
}

if (this->binary_->has_dyld_info()) {
if (this->binary_->has_dyld_info() and this->config_.parse_dyldinfo_deeply()) {

try {
this->parse_dyldinfo_binds<MACHO_T>();
Expand Down
2 changes: 2 additions & 0 deletions src/MachO/CMakeLists.txt
Expand Up @@ -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}/ParserConfig.cpp"
)

set(LIEF_MACHO_INCLUDE_FILES
Expand Down Expand Up @@ -78,6 +79,7 @@ set(LIEF_MACHO_INCLUDE_FILES
"${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/ThreadCommand.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/ParserConfig.hpp"
)

source_group("Header Files\\MachO" FILES ${LIEF_MACHO_INCLUDE_FILES})
Expand Down

0 comments on commit 880b99a

Please sign in to comment.