From a16e1c4d13c7071fabe6a5a46b6d6c0fd9565b72 Mon Sep 17 00:00:00 2001
From: Romain Thomas <romainthomasc@gmail.com>
Date: Mon, 2 Apr 2018 08:20:15 +0200
Subject: [PATCH] Expose DataInCode

---
 api/python/MachO/CMakeLists.txt              |  2 +
 api/python/MachO/objects/pyBinary.cpp        | 12 ++-
 api/python/MachO/objects/pyDataCodeEntry.cpp | 86 +++++++++++++++++
 api/python/MachO/objects/pyDataInCode.cpp    | 76 +++++++++++++++
 api/python/MachO/pyMachO.cpp                 |  3 +
 api/python/MachO/pyMachO.hpp                 |  2 +
 api/python/enums_wrapper.hpp                 |  2 +
 doc/sphinx/api/cpp/macho.rst                 | 19 ++++
 doc/sphinx/api/python/macho.rst              | 29 ++++++
 examples/python/macho_reader.py              | 26 ++++++
 include/LIEF/MachO/Binary.hpp                |  8 ++
 include/LIEF/MachO/DataCodeEntry.hpp         | 82 +++++++++++++++++
 include/LIEF/MachO/DataInCode.hpp            | 77 ++++++++++++++++
 include/LIEF/MachO/EnumToString.hpp          |  2 +
 include/LIEF/MachO/hash.hpp                  |  2 +
 include/LIEF/Visitor.hpp                     |  8 ++
 src/MachO/Binary.cpp                         | 15 +++
 src/MachO/BinaryParser.tcc                   | 17 ++++
 src/MachO/CMakeLists.txt                     |  4 +
 src/MachO/DataCodeEntry.cpp                  | 96 +++++++++++++++++++
 src/MachO/DataInCode.cpp                     | 97 ++++++++++++++++++++
 src/MachO/EnumToString.cpp                   | 14 +++
 src/MachO/hash.cpp                           | 13 +++
 tests/macho/macho_tests.py                   | 27 ++++++
 24 files changed, 718 insertions(+), 1 deletion(-)
 create mode 100644 api/python/MachO/objects/pyDataCodeEntry.cpp
 create mode 100644 api/python/MachO/objects/pyDataInCode.cpp
 create mode 100644 include/LIEF/MachO/DataCodeEntry.hpp
 create mode 100644 include/LIEF/MachO/DataInCode.hpp
 create mode 100644 src/MachO/DataCodeEntry.cpp
 create mode 100644 src/MachO/DataInCode.cpp

diff --git a/api/python/MachO/CMakeLists.txt b/api/python/MachO/CMakeLists.txt
index 5da291c..0c0b3ae 100644
--- a/api/python/MachO/CMakeLists.txt
+++ b/api/python/MachO/CMakeLists.txt
@@ -27,6 +27,8 @@ set(LIEF_PYTHON_MACHO_SRC
   "${CMAKE_CURRENT_LIST_DIR}/objects/pyParserConfig.cpp"
   "${CMAKE_CURRENT_LIST_DIR}/objects/pyDynamicSymbolCommand.cpp"
   "${CMAKE_CURRENT_LIST_DIR}/objects/pyCodeSignature.cpp"
+  "${CMAKE_CURRENT_LIST_DIR}/objects/pyDataInCode.cpp"
+  "${CMAKE_CURRENT_LIST_DIR}/objects/pyDataCodeEntry.cpp"
   "${CMAKE_CURRENT_LIST_DIR}/pyMachOStructures.cpp"
 )
 
diff --git a/api/python/MachO/objects/pyBinary.cpp b/api/python/MachO/objects/pyBinary.cpp
index 4869f3e..71f32bc 100644
--- a/api/python/MachO/objects/pyBinary.cpp
+++ b/api/python/MachO/objects/pyBinary.cpp
@@ -236,7 +236,7 @@ void init_MachO_Binary_class(py::module& m) {
         py::return_value_policy::reference)
 
     .def_property_readonly("has_code_signature",
-        &Binary::has_dynamic_symbol_command,
+        &Binary::has_code_signature,
         "``True`` if the binary is signed (i.e. has a " RST_CLASS_REF(lief.MachO.CodeSignature) " command)",
         py::return_value_policy::reference_internal)
 
@@ -245,6 +245,16 @@ void init_MachO_Binary_class(py::module& m) {
         "Return binary's " RST_CLASS_REF(lief.MachO.CodeSignature) " if any.",
         py::return_value_policy::reference)
 
+    .def_property_readonly("has_data_in_code",
+        &Binary::has_data_in_code,
+        "``True`` if the binary has a " RST_CLASS_REF(lief.MachO.DataInCode) " command",
+        py::return_value_policy::reference_internal)
+
+    .def_property_readonly("data_in_code",
+        static_cast<no_const_getter<DataInCode&>>(&Binary::data_in_code),
+        "Return binary's " RST_CLASS_REF(lief.MachO.DataInCode) " if any.",
+        py::return_value_policy::reference)
+
 
     .def("virtual_address_to_offset",
         &Binary::virtual_address_to_offset,
diff --git a/api/python/MachO/objects/pyDataCodeEntry.cpp b/api/python/MachO/objects/pyDataCodeEntry.cpp
new file mode 100644
index 0000000..a42bc9c
--- /dev/null
+++ b/api/python/MachO/objects/pyDataCodeEntry.cpp
@@ -0,0 +1,86 @@
+/* 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/MachO/hash.hpp"
+#include "LIEF/MachO/DataCodeEntry.hpp"
+#include "LIEF/MachO/EnumToString.hpp"
+
+#include "enums_wrapper.hpp"
+
+#include "pyMachO.hpp"
+
+#define PY_ENUM(x) LIEF::MachO::to_string(x), x
+
+template<class T>
+using getter_t = T (DataCodeEntry::*)(void) const;
+
+template<class T>
+using setter_t = void (DataCodeEntry::*)(T);
+
+
+void init_MachO_DataCodeEntry_class(py::module& m) {
+
+
+  py::class_<DataCodeEntry, LIEF::Object> cls(m, "DataCodeEntry");
+
+  cls
+    .def_property("offset",
+        static_cast<getter_t<uint32_t>>(&DataCodeEntry::offset),
+        static_cast<setter_t<uint32_t>>(&DataCodeEntry::offset),
+        "Offset of the data")
+
+    .def_property("length",
+        static_cast<getter_t<uint16_t>>(&DataCodeEntry::length),
+        static_cast<setter_t<uint16_t>>(&DataCodeEntry::length),
+        "Length of the data")
+
+    .def_property("type",
+        static_cast<getter_t<DataCodeEntry::TYPES>>(&DataCodeEntry::type),
+        static_cast<setter_t<DataCodeEntry::TYPES>>(&DataCodeEntry::type),
+        "Type of the entry (" RST_CLASS_REF(lief.MachO.DataCodeEntry.TYPES) "")
+
+
+    .def("__eq__", &DataCodeEntry::operator==)
+    .def("__ne__", &DataCodeEntry::operator!=)
+    .def("__hash__",
+        [] (const DataCodeEntry& func) {
+          return Hash::hash(func);
+        })
+
+
+    .def("__str__",
+        [] (const DataCodeEntry& func)
+        {
+          std::ostringstream stream;
+          stream << func;
+          std::string str = stream.str();
+          return str;
+        });
+
+
+  LIEF::enum_<DataCodeEntry::TYPES>(cls, "TYPES")
+    .value(PY_ENUM(DataCodeEntry::TYPES::UNKNOWN))
+    .value(PY_ENUM(DataCodeEntry::TYPES::DATA))
+    .value(PY_ENUM(DataCodeEntry::TYPES::JUMP_TABLE_8))
+    .value(PY_ENUM(DataCodeEntry::TYPES::JUMP_TABLE_16))
+    .value(PY_ENUM(DataCodeEntry::TYPES::JUMP_TABLE_32))
+    .value(PY_ENUM(DataCodeEntry::TYPES::ABS_JUMP_TABLE_32));
+
+}
diff --git a/api/python/MachO/objects/pyDataInCode.cpp b/api/python/MachO/objects/pyDataInCode.cpp
new file mode 100644
index 0000000..bdeb3a6
--- /dev/null
+++ b/api/python/MachO/objects/pyDataInCode.cpp
@@ -0,0 +1,76 @@
+/* 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/MachO/hash.hpp"
+#include "LIEF/MachO/DataInCode.hpp"
+
+#include "pyMachO.hpp"
+
+template<class T>
+using getter_t = T (DataInCode::*)(void) const;
+
+template<class T>
+using setter_t = void (DataInCode::*)(T);
+
+
+void init_MachO_DataInCode_class(py::module& m) {
+
+  // Init Iterator
+  init_ref_iterator<DataInCode::it_entries>(m);
+
+  py::class_<DataInCode, LoadCommand>(m, "DataInCode")
+    .def_property("data_offset",
+        static_cast<getter_t<uint32_t>>(&DataInCode::data_offset),
+        static_cast<setter_t<uint32_t>>(&DataInCode::data_offset),
+        "Offset in the binary where signature starts")
+
+    .def_property("data_size",
+        static_cast<getter_t<uint32_t>>(&DataInCode::data_size),
+        static_cast<setter_t<uint32_t>>(&DataInCode::data_size),
+        "Size of the raw signature")
+
+    .def_property_readonly("entries",
+        static_cast<DataInCode::it_entries (DataInCode::*)(void)>(&DataInCode::entries),
+        "Iterator over " RST_CLASS_REF(lief.MachO.DataCodeEntry) "",
+        py::return_value_policy::reference_internal)
+
+    .def("add",
+        &DataInCode::add,
+        "Add an new " RST_CLASS_REF(lief.MachO.DataCodeEntry) "",
+        "entry"_a)
+
+    .def("__eq__", &DataInCode::operator==)
+    .def("__ne__", &DataInCode::operator!=)
+    .def("__hash__",
+        [] (const DataInCode& func) {
+          return Hash::hash(func);
+        })
+
+
+    .def("__str__",
+        [] (const DataInCode& func)
+        {
+          std::ostringstream stream;
+          stream << func;
+          std::string str = stream.str();
+          return str;
+        });
+
+}
diff --git a/api/python/MachO/pyMachO.cpp b/api/python/MachO/pyMachO.cpp
index 875bcf7..eeabddd 100644
--- a/api/python/MachO/pyMachO.cpp
+++ b/api/python/MachO/pyMachO.cpp
@@ -52,6 +52,9 @@ void init_MachO_module(py::module& m) {
   init_MachO_DynamicSymbolCommand_class(LIEF_MachO_module);
   init_MachO_CodeSignature_class(LIEF_MachO_module);
 
+  init_MachO_DataInCode_class(LIEF_MachO_module);
+  init_MachO_DataCodeEntry_class(LIEF_MachO_module);
+
   // Enums
   init_MachO_Structures_enum(LIEF_MachO_module);
 }
diff --git a/api/python/MachO/pyMachO.hpp b/api/python/MachO/pyMachO.hpp
index 1be1feb..2b22ce4 100644
--- a/api/python/MachO/pyMachO.hpp
+++ b/api/python/MachO/pyMachO.hpp
@@ -53,6 +53,8 @@ void init_MachO_ThreadCommand_class(py::module&);
 void init_MachO_RPathCommand_class(py::module&);
 void init_MachO_DynamicSymbolCommand_class(py::module&);
 void init_MachO_CodeSignature_class(py::module&);
+void init_MachO_DataInCode_class(py::module&);
+void init_MachO_DataCodeEntry_class(py::module&);
 
 // Enums
 void init_MachO_Structures_enum(py::module&);
diff --git a/api/python/enums_wrapper.hpp b/api/python/enums_wrapper.hpp
index c4df545..357cc8c 100644
--- a/api/python/enums_wrapper.hpp
+++ b/api/python/enums_wrapper.hpp
@@ -20,6 +20,8 @@
 
 #include "LIEF/visibility.h"
 
+namespace py = pybind11;
+
 namespace LIEF {
 
 template <class Type>
diff --git a/doc/sphinx/api/cpp/macho.rst b/doc/sphinx/api/cpp/macho.rst
index 3b01178..58c9ea6 100644
--- a/doc/sphinx/api/cpp/macho.rst
+++ b/doc/sphinx/api/cpp/macho.rst
@@ -234,6 +234,25 @@ Code Signature
 
 ----------
 
+Data In Code
+************
+
+.. doxygenclass:: LIEF::MachO::DataInCode
+   :project: lief
+
+----------
+
+Data Code Entry
+****************
+
+.. doxygenclass:: LIEF::MachO::DataCodeEntry
+   :project: lief
+
+.. doxygenenum:: LIEF::MachO::DataCodeEntry::TYPES
+   :project: lief
+
+----------
+
 Utilities
 *********
 
diff --git a/doc/sphinx/api/python/macho.rst b/doc/sphinx/api/python/macho.rst
index c70b432..27859b8 100644
--- a/doc/sphinx/api/python/macho.rst
+++ b/doc/sphinx/api/python/macho.rst
@@ -293,6 +293,35 @@ Code Signature
 
 ----------
 
+Data In Code
+************
+
+.. autoclass:: lief.MachO.DataInCode
+   :members:
+   :inherited-members:
+   :undoc-members:
+
+----------
+
+Data Code Entry
+***************
+
+.. autoclass:: lief.MachO.DataCodeEntry
+   :members:
+   :inherited-members:
+   :undoc-members:
+
+
+TYPES
+~~~~~
+
+.. autoclass:: lief.MachO.DataCodeEntry.TYPES
+  :members:
+  :inherited-members:
+  :undoc-members:
+
+----------
+
 
 Enums
 *****
diff --git a/examples/python/macho_reader.py b/examples/python/macho_reader.py
index e80d242..4e589db 100644
--- a/examples/python/macho_reader.py
+++ b/examples/python/macho_reader.py
@@ -370,6 +370,25 @@ def print_function_starts(binary):
 
     print("")
 
+@exceptions_handler(Exception)
+def print_data_in_code(binary):
+    format_str = "{:<13} {:<30}"
+    format_hex = "{:<13} 0x{:<28x}"
+    format_dec = "{:<13} {:<30d}"
+
+    print("== Data In Code ==")
+
+    datacode = binary.data_in_code
+
+    print(format_hex.format("Offset:", datacode.data_offset))
+    print(format_hex.format("Size:",   datacode.data_size))
+    print("")
+    for entry in datacode.entries:
+        type_str = str(entry.type).split(".")[-1]
+        print("- {:<14}: 0x{:x} ({:d} bytes)".format(type_str, entry.offset, entry.length))
+    print("")
+
+
 
 
 @exceptions_handler(Exception)
@@ -636,6 +655,10 @@ def main():
             action='store_true', dest='show_dynamic_symbol_command',
             help="Display the 'Symbol Command' command")
 
+    parser.add_argument('--data-in-code',
+            action='store_true', dest='show_data_in_code',
+            help="Display the 'Data In Code' command")
+
     parser.add_argument('--bind-opcodes',
             action='store_true', dest='show_bind_opcodes',
             help='Display the "Bind" opcodes')
@@ -727,6 +750,9 @@ def main():
         if (args.show_dynamic_symbol_command or args.show_all) and binary.has_dynamic_symbol_command:
             print_dynamic_symbol_command(binary)
 
+        if (args.show_data_in_code or args.show_all) and binary.has_data_in_code:
+            print_data_in_code(binary)
+
         if (args.show_rpath_command or args.show_all) and binary.has_rpath:
             print_rpath_command(binary)
 
diff --git a/include/LIEF/MachO/Binary.hpp b/include/LIEF/MachO/Binary.hpp
index bacb4a2..59d9127 100644
--- a/include/LIEF/MachO/Binary.hpp
+++ b/include/LIEF/MachO/Binary.hpp
@@ -42,6 +42,7 @@
 #include "LIEF/MachO/ThreadCommand.hpp"
 #include "LIEF/MachO/RPathCommand.hpp"
 #include "LIEF/MachO/CodeSignature.hpp"
+#include "LIEF/MachO/DataInCode.hpp"
 
 namespace LIEF {
 namespace MachO {
@@ -298,6 +299,13 @@ class LIEF_API Binary : public LIEF::Binary  {
     CodeSignature&       code_signature(void);
     const CodeSignature& code_signature(void) const;
 
+    //! @brief ``true`` if the binaryhas a MachO::DataInCode command.
+    bool has_data_in_code(void) const;
+
+    //! @brief Return the MachO::Signature
+    DataInCode&       data_in_code(void);
+    const DataInCode& data_in_code(void) const;
+
     template<class T>
     LIEF_LOCAL bool has_command(void) const;
 
diff --git a/include/LIEF/MachO/DataCodeEntry.hpp b/include/LIEF/MachO/DataCodeEntry.hpp
new file mode 100644
index 0000000..bff5d77
--- /dev/null
+++ b/include/LIEF/MachO/DataCodeEntry.hpp
@@ -0,0 +1,82 @@
+
+/* 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_DATA_CODE_ENTRY_H_
+#define LIEF_MACHO_DATA_CODE_ENTRY_H_
+#include <string>
+#include <vector>
+#include <iostream>
+
+#include "LIEF/visibility.h"
+#include "LIEF/types.hpp"
+
+#include "LIEF/Object.hpp"
+
+namespace LIEF {
+namespace MachO {
+
+//! Interface of an entry in DataInCode
+class DataCodeEntry : public LIEF::Object {
+  public:
+  enum class TYPES {
+    UNKNOWN           = 0,
+    DATA              = 1,
+    JUMP_TABLE_8      = 2,
+    JUMP_TABLE_16     = 3,
+    JUMP_TABLE_32     = 4,
+    ABS_JUMP_TABLE_32 = 5,
+  };
+
+  public:
+  DataCodeEntry(void);
+  DataCodeEntry(uint32_t off, uint16_t length, TYPES type);
+  DataCodeEntry(const data_in_code_entry* entry);
+
+  DataCodeEntry& operator=(const DataCodeEntry&);
+  DataCodeEntry(const DataCodeEntry&);
+
+  //! Offset of the data
+  uint32_t offset(void) const;
+
+  //! Length of the data
+  uint16_t length(void) const;
+
+  // Type of the data
+  TYPES type(void) const;
+
+  void offset(uint32_t off);
+  void length(uint16_t length);
+  void type(TYPES type);
+
+  virtual ~DataCodeEntry(void);
+
+  bool operator==(const DataCodeEntry& rhs) const;
+  bool operator!=(const DataCodeEntry& rhs) const;
+
+  virtual void accept(Visitor& visitor) const override;
+
+  LIEF_API friend std::ostream& operator<<(std::ostream& os, const DataCodeEntry& entry);
+
+  private:
+  uint32_t offset_;
+  uint16_t length_;
+  TYPES type_;
+};
+
+}
+}
+
+#endif
diff --git a/include/LIEF/MachO/DataInCode.hpp b/include/LIEF/MachO/DataInCode.hpp
new file mode 100644
index 0000000..4e98bca
--- /dev/null
+++ b/include/LIEF/MachO/DataInCode.hpp
@@ -0,0 +1,77 @@
+/* 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_DATA_IN_CODE_COMMAND_H_
+#define LIEF_MACHO_DATA_IN_CODE_COMMAND_H_
+#include <string>
+#include <vector>
+#include <iostream>
+
+#include "LIEF/visibility.h"
+#include "LIEF/types.hpp"
+
+#include "LIEF/MachO/LoadCommand.hpp"
+#include "LIEF/MachO/DataCodeEntry.hpp"
+
+namespace LIEF {
+namespace MachO {
+
+class BinaryParser;
+
+//! Interface of the LC_DATA_IN_CODE command
+class LIEF_API DataInCode : public LoadCommand {
+  friend class BinaryParser;
+  public:
+  using entries_t        = std::vector<DataCodeEntry>;
+  using it_const_entries = const_ref_iterator<const entries_t&>;
+  using it_entries       = ref_iterator<entries_t&>;
+
+  public:
+  DataInCode(void);
+  DataInCode(const linkedit_data_command *cmd);
+
+  DataInCode& operator=(const DataInCode&);
+  DataInCode(const DataInCode&);
+
+  uint32_t data_offset(void) const;
+  uint32_t data_size(void) const;
+
+  void data_offset(uint32_t offset);
+  void data_size(uint32_t size);
+
+  DataInCode& add(const DataCodeEntry& entry);
+
+  it_const_entries entries(void) const;
+  it_entries entries(void);
+
+  virtual ~DataInCode(void);
+
+  bool operator==(const DataInCode& rhs) const;
+  bool operator!=(const DataInCode& rhs) const;
+
+  virtual void accept(Visitor& visitor) const override;
+
+  virtual std::ostream& print(std::ostream& os) const override;
+
+  private:
+  uint32_t  data_offset_;
+  uint32_t  data_size_;
+  entries_t entries_;
+
+};
+
+}
+}
+#endif
diff --git a/include/LIEF/MachO/EnumToString.hpp b/include/LIEF/MachO/EnumToString.hpp
index 3cfd0a2..e6f1009 100644
--- a/include/LIEF/MachO/EnumToString.hpp
+++ b/include/LIEF/MachO/EnumToString.hpp
@@ -18,6 +18,7 @@
 #include "LIEF/visibility.h"
 
 #include "LIEF/MachO/Structures.hpp"
+#include "LIEF/MachO/DataCodeEntry.hpp"
 
 namespace LIEF {
 namespace MachO {
@@ -48,6 +49,7 @@ LIEF_API const char* to_string(BIND_OPCODES e);
 LIEF_API const char* to_string(EXPORT_SYMBOL_KINDS e);
 LIEF_API const char* to_string(VM_PROTECTIONS e);
 LIEF_API const char* to_string(SYMBOL_ORIGINS e);
+LIEF_API const char* to_string(DataCodeEntry::TYPES e);
 
 } // namespace MachO
 } // namespace LIEF
diff --git a/include/LIEF/MachO/hash.hpp b/include/LIEF/MachO/hash.hpp
index 0e31b52..9329189 100644
--- a/include/LIEF/MachO/hash.hpp
+++ b/include/LIEF/MachO/hash.hpp
@@ -53,6 +53,8 @@ class LIEF_API Hash : public LIEF::Hash {
   virtual void visit(const ExportInfo& einfo)                     override;
   virtual void visit(const FunctionStarts& fs)                    override;
   virtual void visit(const CodeSignature& cs)                     override;
+  virtual void visit(const DataInCode& dic)                       override;
+  virtual void visit(const DataCodeEntry& dce)                    override;
 
   virtual ~Hash(void);
 };
diff --git a/include/LIEF/Visitor.hpp b/include/LIEF/Visitor.hpp
index e6c7b18..26b8a54 100644
--- a/include/LIEF/Visitor.hpp
+++ b/include/LIEF/Visitor.hpp
@@ -140,6 +140,8 @@ LIEF_MACHO_FORWARD(BindingInfo)
 LIEF_MACHO_FORWARD(ExportInfo)
 LIEF_MACHO_FORWARD(FunctionStarts)
 LIEF_MACHO_FORWARD(CodeSignature)
+LIEF_MACHO_FORWARD(DataInCode)
+LIEF_MACHO_FORWARD(DataCodeEntry)
 
 
 class LIEF_API Visitor {
@@ -403,6 +405,12 @@ class LIEF_API Visitor {
   //! @brief Method to visit a LIEF::MachO::CodeSignature
   LIEF_MACHO_VISITABLE(CodeSignature)
 
+  //! @brief Method to visit a LIEF::MachO::DataInCode
+  LIEF_MACHO_VISITABLE(DataInCode)
+
+  //! @brief Method to visit a LIEF::MachO::DataCodeEntry
+  LIEF_MACHO_VISITABLE(DataCodeEntry)
+
   template<class T>
   void dispatch(const T& obj);
 
diff --git a/src/MachO/Binary.cpp b/src/MachO/Binary.cpp
index ac0f765..925dee7 100644
--- a/src/MachO/Binary.cpp
+++ b/src/MachO/Binary.cpp
@@ -814,6 +814,21 @@ const CodeSignature& Binary::code_signature(void) const {
 }
 
 
+// DataInCode command
+// +++++++++++++++++++++
+bool Binary::has_data_in_code(void) const {
+  return this->has_command<DataInCode>();
+}
+
+DataInCode& Binary::data_in_code(void) {
+  return this->command<DataInCode>();
+}
+
+const DataInCode& Binary::data_in_code(void) const {
+  return this->command<DataInCode>();
+}
+
+
 
 
 void Binary::accept(LIEF::Visitor& visitor) const {
diff --git a/src/MachO/BinaryParser.tcc b/src/MachO/BinaryParser.tcc
index da7098f..f6a08f2 100644
--- a/src/MachO/BinaryParser.tcc
+++ b/src/MachO/BinaryParser.tcc
@@ -411,6 +411,23 @@ void BinaryParser::parse_load_commands(void) {
           break;
         }
 
+      case LOAD_COMMAND_TYPES::LC_DATA_IN_CODE:
+        {
+
+          const linkedit_data_command* cmd =
+            reinterpret_cast<const linkedit_data_command*>(
+              this->stream_->read(loadcommands_offset, sizeof(linkedit_data_command)));
+          load_command = std::unique_ptr<DataInCode>{new DataInCode{cmd}};
+          DataInCode* datacode = load_command.get()->as<DataInCode>();
+
+          const data_in_code_entry* entries = reinterpret_cast<const data_in_code_entry*>(this->stream_->read(datacode->data_offset(), datacode->data_size()));
+          const size_t nb_entries = datacode->data_size() / sizeof(data_in_code_entry);
+          for (size_t i = 0; i < nb_entries; ++i) {
+            datacode->add(&entries[i]);
+          }
+          break;
+        }
+
 
 
 
diff --git a/src/MachO/CMakeLists.txt b/src/MachO/CMakeLists.txt
index 155f4c4..08160bd 100644
--- a/src/MachO/CMakeLists.txt
+++ b/src/MachO/CMakeLists.txt
@@ -49,6 +49,8 @@ set(LIEF_MACHO_SRC
   "${CMAKE_CURRENT_LIST_DIR}/ParserConfig.cpp"
   "${CMAKE_CURRENT_LIST_DIR}/hash.cpp"
   "${CMAKE_CURRENT_LIST_DIR}/CodeSignature.cpp"
+  "${CMAKE_CURRENT_LIST_DIR}/DataInCode.cpp"
+  "${CMAKE_CURRENT_LIST_DIR}/DataCodeEntry.cpp"
 )
 
 set(LIEF_MACHO_INCLUDE_FILES
@@ -86,6 +88,8 @@ set(LIEF_MACHO_INCLUDE_FILES
   "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/ParserConfig.hpp"
   "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/hash.hpp"
   "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/CodeSignature.hpp"
+  "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/DataInCode.hpp"
+  "${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/MachO/DataCodeEntry.hpp"
   )
 
 source_group("Header Files\\MachO" FILES ${LIEF_MACHO_INCLUDE_FILES})
diff --git a/src/MachO/DataCodeEntry.cpp b/src/MachO/DataCodeEntry.cpp
new file mode 100644
index 0000000..f50d7c3
--- /dev/null
+++ b/src/MachO/DataCodeEntry.cpp
@@ -0,0 +1,96 @@
+/* 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 <numeric>
+#include <iomanip>
+
+#include "LIEF/MachO/hash.hpp"
+
+#include "LIEF/MachO/DataCodeEntry.hpp"
+
+namespace LIEF {
+namespace MachO {
+
+DataCodeEntry& DataCodeEntry::operator=(const DataCodeEntry&) = default;
+DataCodeEntry::DataCodeEntry(const DataCodeEntry&) = default;
+DataCodeEntry::~DataCodeEntry(void) = default;
+
+DataCodeEntry::DataCodeEntry(void) :
+  offset_{0},
+  length_{0},
+  type_{TYPES::UNKNOWN}
+{}
+
+DataCodeEntry::DataCodeEntry(uint32_t off, uint16_t length, TYPES type) :
+  offset_{off},
+  length_{length},
+  type_{type}
+{}
+
+DataCodeEntry::DataCodeEntry(const data_in_code_entry* entry) :
+  offset_{entry->offset},
+  length_{entry->length},
+  type_{static_cast<TYPES>(entry->kind)}
+{}
+
+
+uint32_t DataCodeEntry::offset(void) const {
+  return this->offset_;
+}
+
+uint16_t DataCodeEntry::length(void) const {
+  return this->length_;
+}
+
+DataCodeEntry::TYPES DataCodeEntry::type(void) const {
+  return this->type_;
+}
+
+void DataCodeEntry::offset(uint32_t off) {
+  this->offset_ = off;
+}
+
+void DataCodeEntry::length(uint16_t length) {
+  this->length_ = length;
+}
+
+void DataCodeEntry::type(TYPES type) {
+  this->type_ = type;
+}
+
+void DataCodeEntry::accept(Visitor& visitor) const {
+  visitor.visit(*this);
+}
+
+
+bool DataCodeEntry::operator==(const DataCodeEntry& rhs) const {
+  size_t hash_lhs = Hash::hash(*this);
+  size_t hash_rhs = Hash::hash(rhs);
+  return hash_lhs == hash_rhs;
+}
+
+bool DataCodeEntry::operator!=(const DataCodeEntry& rhs) const {
+  return not (*this == rhs);
+}
+
+std::ostream& operator<<(std::ostream& os, const DataCodeEntry& entry) {
+  return os;
+}
+
+
+
+
+}
+}
diff --git a/src/MachO/DataInCode.cpp b/src/MachO/DataInCode.cpp
new file mode 100644
index 0000000..48131b3
--- /dev/null
+++ b/src/MachO/DataInCode.cpp
@@ -0,0 +1,97 @@
+/* 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 <numeric>
+#include <iomanip>
+
+#include "LIEF/MachO/hash.hpp"
+
+#include "LIEF/MachO/DataInCode.hpp"
+
+namespace LIEF {
+namespace MachO {
+
+DataInCode::DataInCode(void) = default;
+DataInCode& DataInCode::operator=(const DataInCode&) = default;
+DataInCode::DataInCode(const DataInCode&) = default;
+DataInCode::~DataInCode(void) = default;
+
+DataInCode::DataInCode(const linkedit_data_command *cmd) :
+  LoadCommand::LoadCommand{static_cast<LOAD_COMMAND_TYPES>(cmd->cmd), cmd->cmdsize},
+  data_offset_{cmd->dataoff},
+  data_size_{cmd->datasize}
+{}
+
+uint32_t DataInCode::data_offset(void) const {
+  return this->data_offset_;
+}
+
+uint32_t DataInCode::data_size(void) const {
+  return this->data_size_;
+}
+
+void DataInCode::data_offset(uint32_t offset) {
+  this->data_offset_ = offset;
+}
+
+void DataInCode::data_size(uint32_t size) {
+  this->data_size_ = size;
+}
+
+
+DataInCode& DataInCode::add(const DataCodeEntry& entry) {
+  this->entries_.push_back(entry);
+  return *this;
+}
+
+
+DataInCode::it_const_entries DataInCode::entries(void) const {
+  return this->entries_;
+}
+
+DataInCode::it_entries DataInCode::entries(void) {
+  return this->entries_;
+}
+
+
+void DataInCode::accept(Visitor& visitor) const {
+  visitor.visit(*this);
+}
+
+
+bool DataInCode::operator==(const DataInCode& rhs) const {
+  size_t hash_lhs = Hash::hash(*this);
+  size_t hash_rhs = Hash::hash(rhs);
+  return hash_lhs == hash_rhs;
+}
+
+bool DataInCode::operator!=(const DataInCode& rhs) const {
+  return not (*this == rhs);
+}
+
+
+std::ostream& DataInCode::print(std::ostream& os) const {
+  LoadCommand::print(os);
+  os << std::left;
+  os << std::endl;
+  os << "Data location:" << std::endl;
+  os << std::setw(8) << "Offset" << ": 0x" << this->data_offset() << std::endl;
+  os << std::setw(8) << "Size"   << ": 0x" << this->data_size()   << std::endl;
+  return os;
+}
+
+
+}
+}
diff --git a/src/MachO/EnumToString.cpp b/src/MachO/EnumToString.cpp
index a512106..eeeabb1 100644
--- a/src/MachO/EnumToString.cpp
+++ b/src/MachO/EnumToString.cpp
@@ -470,5 +470,19 @@ const char* to_string(SYMBOL_ORIGINS e) {
   return it == enumStrings.end() ? "Out of range" : it->second;
 }
 
+
+const char* to_string(DataCodeEntry::TYPES e) {
+  CONST_MAP(DataCodeEntry::TYPES, const char*, 6) enumStrings {
+    { DataCodeEntry::TYPES::UNKNOWN,           "UNKNOWN"           },
+    { DataCodeEntry::TYPES::DATA,              "DATA"              },
+    { DataCodeEntry::TYPES::JUMP_TABLE_8,      "JUMP_TABLE_8"      },
+    { DataCodeEntry::TYPES::JUMP_TABLE_16,     "JUMP_TABLE_16"     },
+    { DataCodeEntry::TYPES::JUMP_TABLE_32,     "JUMP_TABLE_32"     },
+    { DataCodeEntry::TYPES::ABS_JUMP_TABLE_32, "ABS_JUMP_TABLE_32" },
+  };
+  auto   it  = enumStrings.find(e);
+  return it == enumStrings.end() ? "UNKNOWN" : it->second;
+}
+
 }
 }
diff --git a/src/MachO/hash.cpp b/src/MachO/hash.cpp
index 002ab55..87995da 100644
--- a/src/MachO/hash.cpp
+++ b/src/MachO/hash.cpp
@@ -245,6 +245,19 @@ void Hash::visit(const CodeSignature& cs) {
   this->process(cs.data_size());
 }
 
+void Hash::visit(const DataInCode& dic) {
+  this->process(dic.data_offset());
+  this->process(dic.data_size());
+  this->process(std::begin(dic.entries()), std::end(dic.entries()));
+}
+
+void Hash::visit(const DataCodeEntry& dce) {
+  this->process(dce.offset());
+  this->process(dce.length());
+  this->process(dce.type());
+}
+
+
 
 
 
diff --git a/tests/macho/macho_tests.py b/tests/macho/macho_tests.py
index f46786c..6aa9459 100644
--- a/tests/macho/macho_tests.py
+++ b/tests/macho/macho_tests.py
@@ -117,6 +117,33 @@ class TestMachO(TestCase):
         self.assertEqual(relocations[0].has_section,  True)
         self.assertEqual(relocations[0].section.name, "__cstring")
 
+    def test_data_in_code(self):
+        binary = lief.parse(get_sample('MachO/MachO32_ARM_binary_data-in-code-LLVM.bin'))
+
+        self.assertTrue(binary.has_data_in_code)
+        dcode = binary.data_in_code
+
+        self.assertEqual(dcode.data_offset, 0x11c)
+        self.assertEqual(dcode.data_size, 0x20)
+
+        self.assertEqual(len(dcode.entries), 4)
+
+        self.assertEqual(dcode.entries[0].type, lief.MachO.DataCodeEntry.TYPES.DATA)
+        self.assertEqual(dcode.entries[0].offset, 0)
+        self.assertEqual(dcode.entries[0].length, 4)
+
+        self.assertEqual(dcode.entries[1].type, lief.MachO.DataCodeEntry.TYPES.JUMP_TABLE_32)
+        self.assertEqual(dcode.entries[1].offset, 4)
+        self.assertEqual(dcode.entries[1].length, 4)
+
+        self.assertEqual(dcode.entries[2].type, lief.MachO.DataCodeEntry.TYPES.JUMP_TABLE_16)
+        self.assertEqual(dcode.entries[2].offset, 8)
+        self.assertEqual(dcode.entries[2].length, 2)
+
+        self.assertEqual(dcode.entries[3].type, lief.MachO.DataCodeEntry.TYPES.JUMP_TABLE_8)
+        self.assertEqual(dcode.entries[3].offset, 10)
+        self.assertEqual(dcode.entries[3].length, 1)
+
 
 
 if __name__ == '__main__':