Skip to content
Permalink
Browse files
Parse LC_SOURCE_VERSION. Resolve #45
  • Loading branch information
romainthomas committed Jul 7, 2017
1 parent ba9be1f commit c359778
Show file tree
Hide file tree
Showing 14 changed files with 322 additions and 0 deletions.
@@ -9,6 +9,7 @@ set(LIEF_PYTHON_MACHO_SRC
"${CMAKE_CURRENT_LIST_DIR}/objects/pyParser.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pySymbol.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyUUID.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pySourceVersion.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyMainCommand.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDylinker.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDyldInfo.cpp"
@@ -144,6 +144,16 @@ void init_MachO_Binary_class(py::module& m) {
"Return binary's " RST_CLASS_REF(lief.MachO.FunctionStarts) " if any.",
py::return_value_policy::reference)

.def_property_readonly("has_source_version",
&Binary::has_source_version,
"``True`` if the binary has a " RST_CLASS_REF(lief.MachO.SourceVersion) " command.",
py::return_value_policy::reference_internal)

.def_property_readonly("source_version",
static_cast<no_const_getter<SourceVersion&>>(&Binary::source_version),
"Return binary's " RST_CLASS_REF(lief.MachO.SourceVersion) " if any.",
py::return_value_policy::reference)



.def("__str__",
@@ -0,0 +1,61 @@
/* 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 <algorithm>

#include <string>
#include <sstream>

#include "LIEF/visitors/Hash.hpp"
#include "LIEF/MachO/SourceVersion.hpp"

#include "pyMachO.hpp"

template<class T>
using getter_t = T (SourceVersion::*)(void) const;

template<class T>
using setter_t = void (SourceVersion::*)(T);


void init_MachO_SourceVersion_class(py::module& m) {

py::class_<SourceVersion, LoadCommand>(m, "SourceVersion")

.def_property("version",
static_cast<getter_t<const version_t&>>(&SourceVersion::version),
static_cast<setter_t<const version_t&>>(&SourceVersion::version),
"TODO",
py::return_value_policy::reference_internal)


.def("__eq__", &SourceVersion::operator==)
.def("__ne__", &SourceVersion::operator!=)
.def("__hash__",
[] (const SourceVersion& version) {
return LIEF::Hash::hash(version);
})


.def("__str__",
[] (const SourceVersion& version)
{
std::ostringstream stream;
stream << version;
std::string str = stream.str();
return str;
});

}
@@ -39,6 +39,7 @@ void init_MachO_module(py::module& m) {
init_MachO_DylinkerCommand_class(LIEF_MachO_module);
init_MachO_DyldInfo_class(LIEF_MachO_module);
init_MachO_FunctionStarts_class(LIEF_MachO_module);
init_MachO_SourceVersion_class(LIEF_MachO_module);


// Enums
@@ -39,6 +39,7 @@ void init_MachO_MainCommand_class(py::module&);
void init_MachO_DylinkerCommand_class(py::module&);
void init_MachO_DyldInfo_class(py::module&);
void init_MachO_FunctionStarts_class(py::module&);
void init_MachO_SourceVersion_class(py::module&);

// Enums
void init_MachO_Structures_enum(py::module&);
@@ -124,3 +124,19 @@ Dyld Info

.. doxygenclass:: LIEF::MachO::DyldInfo
:project: lief


Function starts
***************

.. doxygenclass:: LIEF::MachO::FunctionStarts
:project: lief


----------

Source Version
**************

.. doxygenclass:: LIEF::MachO::SourceVersion
:project: lief
@@ -141,6 +141,17 @@ Function starts

----------

Source Version
**************

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

----------



Enum
****
@@ -253,6 +253,17 @@ def print_dyld_info(binary):

print("")

@exceptions_handler(Exception)
def print_source_version(binary):
print("== Source Version ==")

version = binary.source_version.version

print("Version: {:d}.{:d}.{:d}.{:d}.{:d}".format(*version))

print("")


def main():
parser = argparse.ArgumentParser(usage='%(prog)s [options] <macho-file>')
parser.add_argument('-a', '--all',
@@ -303,6 +314,10 @@ def main():
action='store_true', dest='show_function_starts',
help='Display the FunctionStarts command')

parser.add_argument('--source-version',
action='store_true', dest='show_source_version',
help="Display the 'Source Version' command")

parser.add_argument("binary",
metavar="<macho-file>",
help='Target Mach-O File')
@@ -353,6 +368,9 @@ def main():
if (args.show_function_starts or args.show_all) and binary.has_function_starts:
print_function_starts(binary)

if (args.show_source_version or args.show_all) and binary.has_source_version:
print_source_version(binary)


if __name__ == "__main__":
main()
@@ -37,6 +37,7 @@
#include "LIEF/MachO/DynamicSymbolCommand.hpp"
#include "LIEF/MachO/DyldInfo.hpp"
#include "LIEF/MachO/FunctionStarts.hpp"
#include "LIEF/MachO/SourceVersion.hpp"

namespace LIEF {
namespace MachO {
@@ -202,6 +203,13 @@ class DLL_PUBLIC Binary : public LIEF::Binary {
FunctionStarts& function_starts(void);
const FunctionStarts& function_starts(void) const;

//! @brief ``true`` if the binary has a MachO::SourceVersion command.
bool has_source_version(void) const;

//! @brief Return the MachO::SourceVersion command
SourceVersion& source_version(void);
const SourceVersion& source_version(void) const;

template<class T>
bool has_command(void) const;

@@ -0,0 +1,58 @@
/* 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_SOURCE_VERSION_COMMAND_H_
#define LIEF_MACHO_SOURCE_VERSION_COMMAND_H_
#include <string>
#include <vector>
#include <iostream>
#include <array>

#include "LIEF/visibility.h"
#include "LIEF/types.hpp"

#include "LIEF/MachO/LoadCommand.hpp"

namespace LIEF {
namespace MachO {
using version_t = std::array<uint32_t, 5>;

class DLL_PUBLIC SourceVersion : public LoadCommand {
public:
SourceVersion(void);
SourceVersion(const source_version_command *version_cmd);

SourceVersion& operator=(const SourceVersion& copy);
SourceVersion(const SourceVersion& copy);

virtual ~SourceVersion(void);

const version_t& version(void) const;
void version(const version_t& version);

bool operator==(const SourceVersion& rhs) const;
bool operator!=(const SourceVersion& rhs) const;

virtual void accept(Visitor& visitor) const override;

virtual std::ostream& print(std::ostream& os) const override;

private:
version_t version_;
};

}
}
#endif
@@ -554,6 +554,21 @@ const FunctionStarts& Binary::function_starts(void) const {
return this->get_command<FunctionStarts>();
}

// Source Version
// ++++++++++++++
bool Binary::has_source_version(void) const {
return this->has_command<SourceVersion>();
}

SourceVersion& Binary::source_version(void) {
return this->get_command<SourceVersion>();
}

const SourceVersion& Binary::source_version(void) const {
return this->get_command<SourceVersion>();
}




void Binary::accept(LIEF::Visitor& visitor) const {
@@ -15,6 +15,7 @@
*/
#include "LIEF/MachO/DyldInfo.hpp"
#include "LIEF/MachO/FunctionStarts.hpp"
#include "LIEF/MachO/SourceVersion.hpp"

#include "easylogging++.h"

@@ -247,6 +248,39 @@ void BinaryParser::parse_load_commands(void) {
break;
}

// ===============
// Source Version
// ===============
case LOAD_COMMAND_TYPES::LC_SOURCE_VERSION:
{
LOG(DEBUG) << "[+] Parsing LC_SOURCE_VERSION";

const source_version_command* cmd =
reinterpret_cast<const source_version_command*>(
this->stream_->read(loadcommands_offset, sizeof(version_min_command)));

load_command = new SourceVersion{cmd};
LOG(DEBUG) << "Version: " << std::hex << cmd->version;
break;
}

//case LOAD_COMMAND_TYPES::LC_VERSION_MIN_MACOSX:
//case LOAD_COMMAND_TYPES::LC_VERSION_MIN_IPHONEOS:
// {
// LOG(DEBUG) << "[+] Parsing " << to_string(static_cast<LOAD_COMMAND_TYPES>(command->cmd));

// const version_min_command* cmd =
// reinterpret_cast<const version_min_command*>(
// this->stream_->read(loadcommands_offset, sizeof(version_min_command)));
// LOG(DEBUG) << "Version: " << std::hex << cmd->version;
// LOG(DEBUG) << "SDK: " << std::hex << cmd->sdk;

// load_command = new LoadCommand{command};
// break;
// }




//case LOAD_COMMAND_TYPES::LC_TWOLEVEL_HINTS:
// {
@@ -36,6 +36,7 @@ set(LIEF_MACHO_SRC
"${CMAKE_CURRENT_LIST_DIR}/Binary.tcc"
"${CMAKE_CURRENT_LIST_DIR}/BinaryParser.tcc"
"${CMAKE_CURRENT_LIST_DIR}/FunctionStarts.cpp"
"${CMAKE_CURRENT_LIST_DIR}/SourceVersion.cpp"
)

set(LIEF_MACHO_INCLUDE_FILES
@@ -60,6 +61,7 @@ set(LIEF_MACHO_INCLUDE_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/FunctionStarts.hpp"
"${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/MachO/Structures.hpp"
"${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/MachO/enums.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/SourceVersion.hpp"
)

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

0 comments on commit c359778

Please sign in to comment.