Compare commits
23
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3ea0d510b | ||
|
|
91bfa9e952 | ||
|
|
097b35511e | ||
|
|
1dd7317a0c | ||
|
|
0e12916531 | ||
|
|
9fb11539da | ||
|
|
980ed6b3fb | ||
|
|
a6d9ea90a2 | ||
|
|
8d20b9ba65 | ||
|
|
eb24a317fa | ||
|
|
c0fa4a6455 | ||
|
|
3970c4d4e2 | ||
|
|
96c7e90231 | ||
|
|
badfcf69a7 | ||
|
|
d45e1946e3 | ||
|
|
62d4fb61ea | ||
|
|
0c88cc740f | ||
|
|
b2b7783ec0 | ||
|
|
9790ddfa82 | ||
|
|
986a30e014 | ||
|
|
03a18cb202 | ||
|
|
c37ee0742a | ||
|
|
2ab604d36f |
+23
-16
@@ -21,8 +21,8 @@ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git"
|
||||
include(LIEFGit)
|
||||
else()
|
||||
set(LIEF_VERSION_MAJOR "0")
|
||||
set(LIEF_VERSION_MINOR "12")
|
||||
set(LIEF_VERSION_PATCH "0")
|
||||
set(LIEF_VERSION_MINOR "11")
|
||||
set(LIEF_VERSION_PATCH "3")
|
||||
endif()
|
||||
|
||||
# LIEF Project
|
||||
@@ -101,6 +101,7 @@ set(LIEF_PUBLIC_INCLUDE_FILES)
|
||||
set(LIEF_PRIVATE_INCLUDE_FILES)
|
||||
|
||||
set(LIBLIEF_SOURCE_FILES
|
||||
"${ELG_CC_PATH}"
|
||||
"${mbedtls_src_crypto}"
|
||||
"${mbedtls_src_x509}"
|
||||
"${mbedtls_src_tls}"
|
||||
@@ -116,7 +117,6 @@ set(LIBLIEF_SOURCE_FILES
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/Visitor.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/BinaryStream/BinaryStream.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/BinaryStream/VectorStream.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/BinaryStream/MemoryStream.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/BinaryStream/Convert.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/visitors/hash.cpp")
|
||||
|
||||
@@ -141,7 +141,6 @@ set(LIEF_INC_FILES
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/visitor_macros.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/BinaryStream/BinaryStream.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/BinaryStream/VectorStream.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/BinaryStream/MemoryStream.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/BinaryStream/Convert.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/hash_stream.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/frozen.hpp")
|
||||
@@ -185,7 +184,7 @@ if(CMAKE_BUILD_TYPE MATCHES Debug AND UNIX)
|
||||
target_compile_options(LIB_LIEF PRIVATE -g -O0)
|
||||
endif()
|
||||
|
||||
if(BUILD_SHARED_LIBS OR LIEF_FORCE_API_EXPORTS)
|
||||
if(BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(LIB_LIEF PRIVATE -DLIEF_EXPORTS)
|
||||
else()
|
||||
target_compile_definitions(LIB_LIEF PRIVATE -DLIEF_STATIC)
|
||||
@@ -230,10 +229,6 @@ endif()
|
||||
target_compile_definitions(LIB_LIEF PRIVATE SPDLOG_DISABLE_DEFAULT_LOGGER
|
||||
SPDLOG_FUNCTION=)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
|
||||
target_compile_definitions(LIB_LIEF PRIVATE SPDLOG_NO_EXCEPTIONS SPDLOG_NO_THREAD_ID)
|
||||
endif()
|
||||
|
||||
# Frozen Configuration
|
||||
# ====================
|
||||
if(LIEF_FROZEN_ENABLED)
|
||||
@@ -293,7 +288,7 @@ list(APPEND LIEF_PUBLIC_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include/"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/include/")
|
||||
|
||||
list(APPEND LIEF_PRIVATE_INCLUDE_DIR "${LIEF_PUBLIC_INCLUDE_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src" "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src" "${CMAKE_BINARY_DIR}")
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/LIEF.pc.in ${CMAKE_CURRENT_BINARY_DIR}/LIEF.pc
|
||||
@ONLY)
|
||||
@@ -307,7 +302,8 @@ source_group("mbedtls\\tls" FILES ${mbedtls_src_tls})
|
||||
# Library definition
|
||||
# ==================
|
||||
target_include_directories(
|
||||
LIB_LIEF SYSTEM PRIVATE "${MBEDTLS_INCLUDE_DIRS}")
|
||||
LIB_LIEF SYSTEM PRIVATE "${SPDLOG_SOURCE_DIR}/include"
|
||||
"${MBEDTLS_INCLUDE_DIRS}")
|
||||
|
||||
target_include_directories(
|
||||
LIB_LIEF
|
||||
@@ -354,8 +350,7 @@ target_sources(LIB_LIEF PRIVATE
|
||||
${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/third-party/utfcpp/utf8.h)
|
||||
|
||||
|
||||
add_dependencies(LIB_LIEF lief_mbed_tls)
|
||||
target_link_libraries(LIB_LIEF PRIVATE lief_spdlog)
|
||||
add_dependencies(LIB_LIEF lief_spdlog lief_mbed_tls)
|
||||
|
||||
# Flags definition
|
||||
# ----------------
|
||||
@@ -486,8 +481,20 @@ if(LIEF_COVERAGE)
|
||||
target_link_libraries(LIB_LIEF gcov)
|
||||
endif()
|
||||
|
||||
set_target_properties(LIB_LIEF PROPERTIES OUTPUT_NAME LIEF CLEAN_DIRECT_OUTPUT 1)
|
||||
|
||||
if(MSVC)
|
||||
string(TOLOWER "${CMAKE_BUILD_TYPE}" build_type)
|
||||
if(build_type STREQUAL "debug")
|
||||
set(CRT_OUTPUT_SUFFIX ${LIEF_USE_CRT_DEBUG})
|
||||
else()
|
||||
set(CRT_OUTPUT_SUFFIX ${LIEF_USE_CRT_RELEASE})
|
||||
endif()
|
||||
set_target_properties(LIB_LIEF PROPERTIES OUTPUT_NAME LIEF${CRT_OUTPUT_SUFFIX}
|
||||
CLEAN_DIRECT_OUTPUT 1)
|
||||
else()
|
||||
set_target_properties(LIB_LIEF PROPERTIES OUTPUT_NAME LIEF CLEAN_DIRECT_OUTPUT
|
||||
1)
|
||||
endif()
|
||||
|
||||
# Set a default build type if none was specified
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
@@ -610,11 +617,11 @@ install(
|
||||
COMPONENT config)
|
||||
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/LIEF.pc
|
||||
FILES ${CMAKE_BINARY_DIR}/LIEF.pc
|
||||
DESTINATION lib/pkgconfig
|
||||
COMPONENT libraries)
|
||||
|
||||
export(TARGETS LIB_LIEF lief_spdlog FILE LIEFExport.cmake)
|
||||
export(TARGETS LIB_LIEF FILE LIEFExport.cmake)
|
||||
|
||||
# Package
|
||||
# ======================
|
||||
|
||||
@@ -73,7 +73,6 @@ Main features:
|
||||
- [Android formats](https://lief.quarkslab.com/doc/latest/tutorials/10_android_formats.html)
|
||||
- [Mach-O modification](https://lief.quarkslab.com/doc/latest/tutorials/11_macho_modification.html)
|
||||
- [ELF Coredump](https://lief.quarkslab.com/doc/latest/tutorials/12_elf_coredump.html)
|
||||
- [PE Authenticode](https://lief.quarkslab.com/doc/latest/tutorials/13_pe_authenticode.html)
|
||||
- [Contact](#contact)
|
||||
- [About](#about)
|
||||
- [Authors](#authors)
|
||||
@@ -97,13 +96,60 @@ pip install lief
|
||||
To install nightlty build:
|
||||
|
||||
```console
|
||||
pip install [--user] --index-url https://lief.quarkslab.com/packages lief==0.12.0.dev0
|
||||
pip install [--user] --index-url https://lief.quarkslab.com/packages lief==0.11.0.dev0
|
||||
```
|
||||
|
||||
### Packages
|
||||
|
||||
* **Nightly**: https://github.com/lief-project/packages/tree/gh-pages
|
||||
* **v0.11.4**: https://github.com/lief-project/LIEF/releases/tag/0.11.4
|
||||
<table>
|
||||
<tr><td colspan="4"><a href="https://lief-project.github.io/packages/sdk"><img src="https://img.shields.io/badge/release-master-brightgreen.svg?style=default"></a></td></tr>
|
||||
<tr>
|
||||
<th>Linux</th>
|
||||
<th>Windows - x86</th>
|
||||
<th>Windows - x86-64</th>
|
||||
<th>OSX</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><a href="https://lief-project.github.io/packages/sdk/LIEF-0.11.0-Linux.tar.gz">SDK</a></td>
|
||||
<td><a href="https://lief-project.github.io/packages/sdk/LIEF-0.11.0-win32.zip">SDK</a></td>
|
||||
<td><a href="https://lief-project.github.io/packages/sdk/LIEF-0.11.0-win64.zip">SDK</a></td>
|
||||
<td><a href="https://lief-project.github.io/packages/sdk/LIEF-0.11.0-Darwin.tar.gz">SDK</a></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="4"><p align="center"><a href="https://lief-project.github.io/packages/lief">Python</a></p></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table>
|
||||
<tr><td colspan="6"><b><img src="https://img.shields.io/badge/release-0.10.1-brightgreen.svg?style=default"></b></td></tr>
|
||||
<tr>
|
||||
<th>Linux</th>
|
||||
<th>Windows</th>
|
||||
<th>OSX</th>
|
||||
<th>Documentation</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><a href="https://github.com/lief-project/LIEF/releases/download/0.10.1/LIEF-0.10.1-Linux.tar.gz">SDK</a></td>
|
||||
<td>
|
||||
<a href="https://github.com/lief-project/LIEF/releases/download/0.10.1/LIEF-0.10.1-win32.zip">SDK - x86</a>
|
||||
<br />
|
||||
<a href="https://github.com/lief-project/LIEF/releases/download/0.10.1/LIEF-0.10.1-win64.zip">SDK - x86-64</a>
|
||||
</td>
|
||||
<td><a href="https://github.com/lief-project/LIEF/releases/download/0.10.1/LIEF-0.10.1-Darwin.tar.gz">SDK</a></td>
|
||||
|
||||
<td><a href="https://github.com/lief-project/LIEF/releases/download/0.10.1/documentation-0.10.1.tar.gz">Sphinx + Doxygen</a></td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td colspan="3"><p align="center"><a href="https://github.com/lief-project/LIEF/releases/download/0.10.1/">Python</a></p></td>
|
||||
</tr>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
Here are guides to install or integrate LIEF:
|
||||
|
||||
@@ -206,7 +252,7 @@ Romain Thomas ([@rh0main](https://twitter.com/rh0main)) - [Quarkslab](https://ww
|
||||
|
||||
### License
|
||||
|
||||
LIEF is provided under the [Apache 2.0 license](https://github.com/lief-project/LIEF/blob/0.11.2/LICENSE).
|
||||
LIEF is provided under the [Apache 2.0 license](https://github.com/lief-project/LIEF/blob/0.10.1/LICENSE).
|
||||
|
||||
### Bibtex
|
||||
|
||||
@@ -221,4 +267,9 @@ LIEF is provided under the [Apache 2.0 license](https://github.com/lief-project/
|
||||
|
||||
```
|
||||
|
||||
---------------
|
||||
|
||||
<p align="center" >
|
||||
<img width="40%" src="http://lief.quarkslab.com/resources/QB-big.png"/>
|
||||
</p>
|
||||
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
#define LIEF_C_TYPES_H_
|
||||
#include <stdint.h>
|
||||
#ifndef __cplusplus
|
||||
#ifndef bool
|
||||
typedef int bool;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#include "pyAbstract.hpp"
|
||||
#include "LIEF/Abstract/Binary.hpp"
|
||||
@@ -100,7 +99,8 @@ void create<Binary>(py::module& m) {
|
||||
imported_libraries_encoded.reserve(imported_libraries.size());
|
||||
|
||||
std::transform(
|
||||
std::begin(imported_libraries), std::end(imported_libraries),
|
||||
std::begin(imported_libraries),
|
||||
std::end(imported_libraries),
|
||||
std::back_inserter(imported_libraries_encoded),
|
||||
&safe_string_converter);
|
||||
return imported_libraries_encoded;
|
||||
@@ -184,14 +184,6 @@ void create<Binary>(py::module& m) {
|
||||
"Return all **virtual addresses** that *use* the ``address`` given in parameter",
|
||||
"virtual_address"_a)
|
||||
|
||||
.def("offset_to_virtual_address", &Binary::offset_to_virtual_address,
|
||||
"Convert an offset into a virtual address.",
|
||||
"offset"_a, "slide"_a = 0)
|
||||
|
||||
.def_property_readonly("imagebase",
|
||||
&Binary::imagebase,
|
||||
"Default image base (i.e. if the ASLR is not enabled)")
|
||||
|
||||
.def("__str__",
|
||||
[] (const Binary& binary)
|
||||
{
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <sstream>
|
||||
#include "pyAbstract.hpp"
|
||||
|
||||
#include "LIEF/Abstract/hash.hpp"
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <sstream>
|
||||
#include "pyAbstract.hpp"
|
||||
#include "LIEF/Abstract/Section.hpp"
|
||||
|
||||
|
||||
@@ -17,12 +17,13 @@ macro(ADD_FLAG_IF_SUPPORTED flag name)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
find_package(Python3 COMPONENTS Interpreter Development REQUIRED)
|
||||
set(PYTHON_VERSION "3.5" CACHE STRING "Python Version to use")
|
||||
find_package(PythonLibsNew EXACT ${PYTHON_VERSION} MODULE REQUIRED)
|
||||
|
||||
message(STATUS "Python version: ${Python3_VERSION}")
|
||||
message(STATUS "Python lib: ${Python3_LIBRARIES}")
|
||||
message(STATUS "Python include: ${Python3_INCLUDE_DIRS}")
|
||||
message(STATUS "Python interpreter: ${Python3_EXECUTABLE}")
|
||||
message(STATUS "Python version: ${PYTHON_VERSION}")
|
||||
message(STATUS "Python lib: ${PYTHON_LIBRARY}")
|
||||
message(STATUS "Python include: ${PYTHON_INCLUDE_DIR}")
|
||||
message(STATUS "Python interpreter: ${PYTHON_EXECUTABLE}")
|
||||
|
||||
set(PYBIND11_VERSION 2.6.1)
|
||||
set(PYBIND11_SHA256 SHA256=e3f9408fca4e8ebf2d22229d5256adb49098073832aad87f3f6078d91a6942b2)
|
||||
@@ -74,9 +75,7 @@ set(LIEF_PYTHON_HDR
|
||||
|
||||
source_group("Header Files" FILES ${LIEF_PYTHON_BASIC_HDR})
|
||||
|
||||
Python3_add_library(pyLIEF MODULE
|
||||
${LIEF_PYTHON_SRC} ${LIEF_PYTHON_HDR}
|
||||
)
|
||||
add_library(pyLIEF SHARED ${LIEF_PYTHON_SRC} ${LIEF_PYTHON_HDR})
|
||||
|
||||
target_include_directories(pyLIEF PUBLIC
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/"
|
||||
|
||||
@@ -7,7 +7,6 @@ set(LIEF_PYTHON_DEX_SRC
|
||||
"${CMAKE_CURRENT_LIST_DIR}/objects/pyParser.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/objects/pyFile.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/objects/pyClass.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/objects/pyField.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/objects/pyMethod.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/objects/pyCodeInfo.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/objects/pyMapList.cpp"
|
||||
|
||||
@@ -73,15 +73,6 @@ void create<Class>(py::module& m) {
|
||||
"Iterator over " RST_CLASS_REF(lief.DEX.Method) " (s) having the given name",
|
||||
"name"_a)
|
||||
|
||||
.def_property_readonly("fields",
|
||||
static_cast<no_const_getter_t<it_fields>>(&Class::fields),
|
||||
"Iterator over " RST_CLASS_REF(lief.DEX.Field) " in this class")
|
||||
|
||||
.def("get_field",
|
||||
static_cast<it_fields(Class::*)(const std::string&)>(&Class::fields),
|
||||
"Iterator over " RST_CLASS_REF(lief.DEX.Field) " (s) having the given name",
|
||||
"name"_a)
|
||||
|
||||
.def_property_readonly("access_flags",
|
||||
static_cast<getter_t<Class::access_flags_list_t>>(&Class::access_flags),
|
||||
"List of " RST_CLASS_REF(lief.DEX.ACCESS_FLAGS) "")
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
#include "LIEF/DEX/Field.hpp"
|
||||
#include "LIEF/DEX/hash.hpp"
|
||||
|
||||
#include "pyDEX.hpp"
|
||||
|
||||
namespace LIEF {
|
||||
namespace DEX {
|
||||
|
||||
template<class T>
|
||||
using getter_t = T (Field::*)(void) const;
|
||||
|
||||
template<class T>
|
||||
using no_const_getter_t = T (Field::*)(void);
|
||||
|
||||
template<class T>
|
||||
using setter_t = void (Field::*)(T);
|
||||
|
||||
|
||||
template<>
|
||||
void create<Field>(py::module& m) {
|
||||
|
||||
py::class_<Field, LIEF::Object>(m, "Field", "DEX Field representation")
|
||||
.def_property_readonly("name",
|
||||
&Field::name,
|
||||
"Field's name")
|
||||
|
||||
.def_property_readonly("index",
|
||||
&Field::index,
|
||||
"Original DEX file index of the field")
|
||||
|
||||
.def_property_readonly("has_class",
|
||||
&Field::has_class,
|
||||
"True if a class is associated with this field")
|
||||
|
||||
.def_property_readonly("cls",
|
||||
static_cast<no_const_getter_t<Class&>>(&Field::cls),
|
||||
"" RST_CLASS_REF(lief.DEX.Class) " associated with this field")
|
||||
|
||||
.def_property_readonly("is_static",
|
||||
&Field::is_static,
|
||||
"True if the field is static")
|
||||
|
||||
.def_property_readonly("type",
|
||||
static_cast<no_const_getter_t<Type&>>(&Field::type),
|
||||
"" RST_CLASS_REF(lief.DEX.Type) " of this field", py::return_value_policy::reference)
|
||||
|
||||
.def_property_readonly("access_flags",
|
||||
static_cast<getter_t<Field::access_flags_list_t>>(&Field::access_flags),
|
||||
"List of " RST_CLASS_REF(lief.DEX.ACCESS_FLAGS) "")
|
||||
|
||||
.def("has",
|
||||
static_cast<bool(Field::*)(ACCESS_FLAGS) const>(&Field::has),
|
||||
"Check if the given " RST_CLASS_REF(lief.DEX.ACCESS_FLAGS) " is present",
|
||||
"flag"_a)
|
||||
|
||||
.def("__eq__", &Field::operator==)
|
||||
.def("__ne__", &Field::operator!=)
|
||||
.def("__hash__",
|
||||
[] (const Field& fld) {
|
||||
return Hash::hash(fld);
|
||||
})
|
||||
|
||||
.def("__str__",
|
||||
[] (const Field& fld) {
|
||||
std::ostringstream stream;
|
||||
stream << fld;
|
||||
return stream.str();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -68,10 +68,6 @@ void create<File>(py::module& m) {
|
||||
static_cast<no_const_getter_t<it_methods>>(&File::methods),
|
||||
"Iterator over Dex " RST_CLASS_REF(lief.DEX.Method) "")
|
||||
|
||||
.def_property_readonly("fields",
|
||||
static_cast<no_const_getter_t<it_fields>>(&File::fields),
|
||||
"Iterator over Dex " RST_CLASS_REF(lief.DEX.Field) "")
|
||||
|
||||
.def_property_readonly("strings",
|
||||
static_cast<no_const_getter_t<it_strings>>(&File::strings),
|
||||
"Iterator over Dex strings")
|
||||
|
||||
@@ -34,7 +34,6 @@ void init_objects(py::module& m) {
|
||||
CREATE(Header, m);
|
||||
CREATE(Class, m);
|
||||
CREATE(Method, m);
|
||||
CREATE(Field, m);
|
||||
CREATE(Prototype, m);
|
||||
CREATE(Type, m);
|
||||
CREATE(MapList, m);
|
||||
|
||||
@@ -49,7 +49,6 @@ SPECIALIZE_CREATE(File);
|
||||
SPECIALIZE_CREATE(Header);
|
||||
SPECIALIZE_CREATE(Class);
|
||||
SPECIALIZE_CREATE(Method);
|
||||
SPECIALIZE_CREATE(Field);
|
||||
SPECIALIZE_CREATE(Prototype);
|
||||
SPECIALIZE_CREATE(Type);
|
||||
SPECIALIZE_CREATE(MapList);
|
||||
|
||||
@@ -25,7 +25,6 @@ void init_iterators(py::module& m) {
|
||||
init_ref_iterator<it_dex_files>(m, "lief.DEX.it_dex_files");
|
||||
init_ref_iterator<it_classes>(m, "lief.DEX.it_classes");
|
||||
init_ref_iterator<it_methods>(m, "lief.DEX.it_methods");
|
||||
init_ref_iterator<it_fields>(m, "lief.DEX.it_fields");
|
||||
init_ref_iterator<it_strings>(m, "lief.DEX.it_strings");
|
||||
init_ref_iterator<it_protypes>(m, "lief.DEX.it_protypes");
|
||||
}
|
||||
|
||||
@@ -203,8 +203,8 @@ void init_enums(py::module& m) {
|
||||
.value(PY_ENUM(ARCH::EM_8051))
|
||||
.value(PY_ENUM(ARCH::EM_STXP7X))
|
||||
.value(PY_ENUM(ARCH::EM_NDS32))
|
||||
.value("ECOG1", ARCH::EM_ECOG1)
|
||||
.value("ECOG1X", ARCH::EM_ECOG1X)
|
||||
.value("ECOG1", ARCH::EM_ECOG1)
|
||||
.value(PY_ENUM(ARCH::EM_ECOG1X))
|
||||
.value(PY_ENUM(ARCH::EM_MAXQ30))
|
||||
.value(PY_ENUM(ARCH::EM_XIMO16))
|
||||
.value(PY_ENUM(ARCH::EM_MANIK))
|
||||
@@ -254,7 +254,6 @@ void init_enums(py::module& m) {
|
||||
.value(PY_ENUM(ARCH::EM_NORC))
|
||||
.value(PY_ENUM(ARCH::EM_CSR_KALIMBA))
|
||||
.value(PY_ENUM(ARCH::EM_AMDGPU))
|
||||
.value(PY_ENUM(ARCH::EM_RISCV))
|
||||
.value(PY_ENUM(ARCH::EM_BPF));
|
||||
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ void create<Binary>(py::module& m) {
|
||||
"name"_a)
|
||||
|
||||
.def("get_symbol",
|
||||
static_cast<no_const_func<Symbol*, const std::string&>>(&Binary::get_symbol),
|
||||
static_cast<no_const_func<Symbol&, const std::string&>>(&Binary::get_symbol),
|
||||
"Return the " RST_CLASS_REF(lief.MachO.Symbol) " from the given name",
|
||||
"name"_a,
|
||||
py::return_value_policy::reference)
|
||||
|
||||
@@ -91,8 +91,8 @@ void create<BuildVersion>(py::module& m) {
|
||||
"Minimal OS version on which this binary was built to run")
|
||||
|
||||
.def_property("sdk",
|
||||
static_cast<getter_t<BuildVersion::version_t>>(&BuildVersion::sdk),
|
||||
static_cast<setter_t<BuildVersion::version_t>>(&BuildVersion::sdk),
|
||||
static_cast<getter_t<BuildVersion::version_t>>(&BuildVersion::minos),
|
||||
static_cast<setter_t<BuildVersion::version_t>>(&BuildVersion::minos),
|
||||
"SDK Version")
|
||||
|
||||
.def_property_readonly("tools",
|
||||
|
||||
@@ -39,13 +39,6 @@ void create<FatBinary>(py::module& m) {
|
||||
"index"_a,
|
||||
py::return_value_policy::reference_internal)
|
||||
|
||||
.def("take",
|
||||
static_cast<std::unique_ptr<Binary>(FatBinary::*)(CPU_TYPES)>(&FatBinary::take),
|
||||
"Return the " RST_CLASS_REF(lief.MachO.Binary) " that matches the "
|
||||
"given " RST_CLASS_REF(lief.MachO.CPU_TYPES) "",
|
||||
"cpu"_a,
|
||||
py::return_value_policy::take_ownership)
|
||||
|
||||
.def("write",
|
||||
&FatBinary::write,
|
||||
"Build a Mach-O universal binary",
|
||||
|
||||
@@ -102,8 +102,6 @@ void create<SegmentCommand>(py::module& m) {
|
||||
static_cast<no_const_getter<it_relocations>>(&SegmentCommand::relocations),
|
||||
"Segment's relocations"
|
||||
)
|
||||
.def_property_readonly("index", &SegmentCommand::index,
|
||||
"Relative index of the segment in the segment table")
|
||||
|
||||
.def_property("content",
|
||||
static_cast<getter_t<const SegmentCommand::content_t&>>(&SegmentCommand::content),
|
||||
|
||||
@@ -247,8 +247,7 @@ void init_enums(py::module& m) {
|
||||
LIEF::enum_<LIEF::MachO::BINDING_CLASS>(m, "BINDING_CLASS")
|
||||
.value(PY_ENUM(LIEF::MachO::BINDING_CLASS::BIND_CLASS_WEAK))
|
||||
.value(PY_ENUM(LIEF::MachO::BINDING_CLASS::BIND_CLASS_LAZY))
|
||||
.value(PY_ENUM(LIEF::MachO::BINDING_CLASS::BIND_CLASS_STANDARD))
|
||||
.value(PY_ENUM(LIEF::MachO::BINDING_CLASS::BIND_CLASS_THREADED));
|
||||
.value(PY_ENUM(LIEF::MachO::BINDING_CLASS::BIND_CLASS_STANDARD));
|
||||
|
||||
|
||||
LIEF::enum_<LIEF::MachO::REBASE_OPCODES>(m, "REBASE_OPCODES")
|
||||
@@ -288,8 +287,7 @@ void init_enums(py::module& m) {
|
||||
.value(PY_ENUM(LIEF::MachO::BIND_OPCODES::BIND_OPCODE_DO_BIND))
|
||||
.value(PY_ENUM(LIEF::MachO::BIND_OPCODES::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB))
|
||||
.value(PY_ENUM(LIEF::MachO::BIND_OPCODES::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED))
|
||||
.value(PY_ENUM(LIEF::MachO::BIND_OPCODES::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB))
|
||||
.value(PY_ENUM(LIEF::MachO::BIND_OPCODES::BIND_OPCODE_THREADED));
|
||||
.value(PY_ENUM(LIEF::MachO::BIND_OPCODES::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB));
|
||||
|
||||
|
||||
LIEF::enum_<LIEF::MachO::EXPORT_SYMBOL_KINDS>(m, "EXPORT_SYMBOL_KINDS")
|
||||
|
||||
@@ -40,8 +40,7 @@ template<>
|
||||
void create<Signature>(py::module& m) {
|
||||
|
||||
py::class_<Signature, LIEF::Object> signature(m, "Signature");
|
||||
LIEF::enum_<Signature::VERIFICATION_FLAGS> verif_flags_enums(signature, "VERIFICATION_FLAGS", py::arithmetic());
|
||||
verif_flags_enums
|
||||
LIEF::enum_<Signature::VERIFICATION_FLAGS>(signature, "VERIFICATION_FLAGS", py::arithmetic())
|
||||
.value("OK", Signature::VERIFICATION_FLAGS::OK)
|
||||
.value("INVALID_SIGNER", Signature::VERIFICATION_FLAGS::INVALID_SIGNER)
|
||||
.value("UNSUPPORTED_ALGORITHM", Signature::VERIFICATION_FLAGS::UNSUPPORTED_ALGORITHM)
|
||||
@@ -54,17 +53,28 @@ void create<Signature>(py::module& m) {
|
||||
.value("BAD_SIGNATURE", Signature::VERIFICATION_FLAGS::BAD_SIGNATURE)
|
||||
.value("NO_SIGNATURE", Signature::VERIFICATION_FLAGS::NO_SIGNATURE)
|
||||
.value("CERT_EXPIRED", Signature::VERIFICATION_FLAGS::CERT_EXPIRED)
|
||||
.value("CERT_FUTURE", Signature::VERIFICATION_FLAGS::CERT_FUTURE);
|
||||
|
||||
py::dict verif_flags_entries = verif_flags_enums.attr("__entries");
|
||||
verif_flags_enums
|
||||
.def("__str__", [verif_flags_entries] (const Signature::VERIFICATION_FLAGS& flags) {
|
||||
.value("CERT_FUTURE", Signature::VERIFICATION_FLAGS::CERT_FUTURE)
|
||||
.def("__str__", [] (const Signature::VERIFICATION_FLAGS& flags) {
|
||||
static const std::array<Signature::VERIFICATION_FLAGS, 13> FLAGS = {
|
||||
Signature::VERIFICATION_FLAGS::OK,
|
||||
Signature::VERIFICATION_FLAGS::INVALID_SIGNER,
|
||||
Signature::VERIFICATION_FLAGS::UNSUPPORTED_ALGORITHM,
|
||||
Signature::VERIFICATION_FLAGS::INCONSISTENT_DIGEST_ALGORITHM,
|
||||
Signature::VERIFICATION_FLAGS::CERT_NOT_FOUND,
|
||||
Signature::VERIFICATION_FLAGS::CORRUPTED_CONTENT_INFO,
|
||||
Signature::VERIFICATION_FLAGS::CORRUPTED_AUTH_DATA,
|
||||
Signature::VERIFICATION_FLAGS::MISSING_PKCS9_MESSAGE_DIGEST,
|
||||
Signature::VERIFICATION_FLAGS::BAD_DIGEST,
|
||||
Signature::VERIFICATION_FLAGS::BAD_SIGNATURE,
|
||||
Signature::VERIFICATION_FLAGS::NO_SIGNATURE,
|
||||
Signature::VERIFICATION_FLAGS::CERT_EXPIRED,
|
||||
Signature::VERIFICATION_FLAGS::CERT_FUTURE,
|
||||
};
|
||||
if (flags == Signature::VERIFICATION_FLAGS::OK) {
|
||||
return Signature::flag_to_string(flags);
|
||||
}
|
||||
std::string flags_str;
|
||||
for (const auto& item : verif_flags_entries) {
|
||||
Signature::VERIFICATION_FLAGS flag = item.second[py::int_(0)].cast<Signature::VERIFICATION_FLAGS>();
|
||||
for (const Signature::VERIFICATION_FLAGS& flag : FLAGS) {
|
||||
if ((flags & flag) == flag and flag != Signature::VERIFICATION_FLAGS::OK) {
|
||||
if (not flags_str.empty()) {
|
||||
flags_str += " | ";
|
||||
|
||||
@@ -1,14 +1 @@
|
||||
set(LIEF_PYTHON_PLATFORM_SRC
|
||||
"${CMAKE_CURRENT_LIST_DIR}/pyPlatform.cpp"
|
||||
)
|
||||
|
||||
set(LIEF_PYTHON_PLATFORM_HDR
|
||||
"${CMAKE_CURRENT_LIST_DIR}/pyPlatform.hpp")
|
||||
|
||||
source_group("Source Files\\Platform" FILES ${LIEF_PYTHON_PLATFORM_SRC})
|
||||
source_group("Header Files\\Platform" FILES ${LIEF_PYTHON_PLATFORM_HDR})
|
||||
|
||||
target_sources(pyLIEF PRIVATE "${LIEF_PYTHON_PLATFORM_HDR}" "${LIEF_PYTHON_PLATFORM_SRC}")
|
||||
target_include_directories(pyLIEF PUBLIC "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_CURRENT_LIST_DIR}/../")
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/android/CMakeLists.txt")
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/* Copyright 2017 - 2021 R. Thomas
|
||||
* Copyright 2017 - 2021 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 "pyPlatform.hpp"
|
||||
#include "enums_wrapper.hpp"
|
||||
|
||||
namespace LIEF {
|
||||
|
||||
void init_python_platforms(py::module& m) {
|
||||
LIEF::enum_<PLATFORMS>(m, "PLATFORMS")
|
||||
.value("UNKNOWN", PLATFORMS::UNKNOWN)
|
||||
.value("LINUX", PLATFORMS::LINUX)
|
||||
.value("ANDROID", PLATFORMS::ANDROID_PLAT)
|
||||
.value("WINDOWS", PLATFORMS::WINDOWS)
|
||||
.value("IOS", PLATFORMS::IOS)
|
||||
.value("OSX", PLATFORMS::OSX);
|
||||
|
||||
m.def("current_platform", ¤t_platform,
|
||||
"Return the current plaform (Linux, Windows, ...) as a :attr:`lief.PLATFORMS` enum");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
/* Copyright 2017 - 2021 R. Thomas
|
||||
* Copyright 2017 - 2021 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 PY_LIEF_PLATFORM_H_
|
||||
#define PY_LIEF_PLATFORM_H_
|
||||
|
||||
#include "LIEF/platforms.hpp"
|
||||
#include "pyLIEF.hpp"
|
||||
|
||||
namespace LIEF {
|
||||
|
||||
void init_python_platforms(py::module&);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -48,7 +48,6 @@
|
||||
|
||||
|
||||
#include "platforms/android/pyAndroid.hpp"
|
||||
#include "platforms/pyPlatform.hpp"
|
||||
|
||||
|
||||
PYBIND11_MODULE(lief, LIEF_module) {
|
||||
@@ -59,8 +58,6 @@ PYBIND11_MODULE(lief, LIEF_module) {
|
||||
LIEF_module.attr("__is_tagged__") = py::bool_(LIEF_TAGGED);
|
||||
LIEF_module.doc() = "Python API for LIEF";
|
||||
|
||||
LIEF::init_python_platforms(LIEF_module);
|
||||
|
||||
init_LIEF_Object_class(LIEF_module);
|
||||
|
||||
init_LIEF_iterators(LIEF_module);
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
# - Find python libraries
|
||||
# This module finds the libraries corresponding to the Python interpreter
|
||||
# FindPythonInterp provides.
|
||||
# This code sets the following variables:
|
||||
#
|
||||
# PYTHONLIBS_FOUND - have the Python libs been found
|
||||
# PYTHON_PREFIX - path to the Python installation
|
||||
# PYTHON_LIBRARIES - path to the python library
|
||||
# PYTHON_INCLUDE_DIRS - path to where Python.h is found
|
||||
# PYTHON_MODULE_EXTENSION - lib extension, e.g. '.so' or '.pyd'
|
||||
# PYTHON_MODULE_PREFIX - lib name prefix: usually an empty string
|
||||
# PYTHON_SITE_PACKAGES - path to installation site-packages
|
||||
# PYTHON_IS_DEBUG - whether the Python interpreter is a debug build
|
||||
#
|
||||
# Thanks to talljimbo for the patch adding the 'LDVERSION' config
|
||||
# variable usage.
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2001-2009 Kitware, Inc.
|
||||
# Copyright 2012 Continuum Analytics, Inc.
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# * Neither the names of Kitware, Inc., the Insight Software Consortium,
|
||||
# nor the names of their contributors may be used to endorse or promote
|
||||
# products derived from this software without specific prior written
|
||||
# permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#=============================================================================
|
||||
|
||||
# Checking for the extension makes sure that `LibsNew` was found and not just `Libs`.
|
||||
if(PYTHONLIBS_FOUND AND PYTHON_MODULE_EXTENSION)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Use the Python interpreter to find the libs.
|
||||
if(PythonLibsNew_FIND_REQUIRED)
|
||||
find_package(PythonInterp ${PythonLibsNew_FIND_VERSION} REQUIRED)
|
||||
else()
|
||||
find_package(PythonInterp ${PythonLibsNew_FIND_VERSION})
|
||||
endif()
|
||||
|
||||
if(NOT PYTHONINTERP_FOUND)
|
||||
set(PYTHONLIBS_FOUND FALSE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# According to http://stackoverflow.com/questions/646518/python-how-to-detect-debug-interpreter
|
||||
# testing whether sys has the gettotalrefcount function is a reliable, cross-platform
|
||||
# way to detect a CPython debug interpreter.
|
||||
#
|
||||
# The library suffix is from the config var LDVERSION sometimes, otherwise
|
||||
# VERSION. VERSION will typically be like "2.7" on unix, and "27" on windows.
|
||||
execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c"
|
||||
"from distutils import sysconfig as s;import sys;import struct;
|
||||
print('.'.join(str(v) for v in sys.version_info));
|
||||
print(sys.prefix);
|
||||
print(s.get_python_inc(plat_specific=True));
|
||||
print(s.get_python_lib(plat_specific=True));
|
||||
print(s.get_config_var('SO'));
|
||||
print(hasattr(sys, 'gettotalrefcount')+0);
|
||||
print(struct.calcsize('@P'));
|
||||
print(s.get_config_var('LDVERSION') or s.get_config_var('VERSION'));
|
||||
print(s.get_config_var('LIBDIR') or '');
|
||||
print(s.get_config_var('MULTIARCH') or '');
|
||||
"
|
||||
RESULT_VARIABLE _PYTHON_SUCCESS
|
||||
OUTPUT_VARIABLE _PYTHON_VALUES
|
||||
ERROR_VARIABLE _PYTHON_ERROR_VALUE)
|
||||
|
||||
if(NOT _PYTHON_SUCCESS MATCHES 0)
|
||||
if(PythonLibsNew_FIND_REQUIRED)
|
||||
message(FATAL_ERROR
|
||||
"Python config failure:\n${_PYTHON_ERROR_VALUE}")
|
||||
endif()
|
||||
set(PYTHONLIBS_FOUND FALSE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Convert the process output into a list
|
||||
if(WIN32)
|
||||
string(REGEX REPLACE "\\\\" "/" _PYTHON_VALUES ${_PYTHON_VALUES})
|
||||
endif()
|
||||
string(REGEX REPLACE ";" "\\\\;" _PYTHON_VALUES ${_PYTHON_VALUES})
|
||||
string(REGEX REPLACE "\n" ";" _PYTHON_VALUES ${_PYTHON_VALUES})
|
||||
list(GET _PYTHON_VALUES 0 _PYTHON_VERSION_LIST)
|
||||
list(GET _PYTHON_VALUES 1 PYTHON_PREFIX)
|
||||
list(GET _PYTHON_VALUES 2 PYTHON_INCLUDE_DIR)
|
||||
list(GET _PYTHON_VALUES 3 PYTHON_SITE_PACKAGES)
|
||||
list(GET _PYTHON_VALUES 4 PYTHON_MODULE_EXTENSION)
|
||||
list(GET _PYTHON_VALUES 5 PYTHON_IS_DEBUG)
|
||||
list(GET _PYTHON_VALUES 6 PYTHON_SIZEOF_VOID_P)
|
||||
list(GET _PYTHON_VALUES 7 PYTHON_LIBRARY_SUFFIX)
|
||||
list(GET _PYTHON_VALUES 8 PYTHON_LIBDIR)
|
||||
list(GET _PYTHON_VALUES 9 PYTHON_MULTIARCH)
|
||||
|
||||
# Make sure the Python has the same pointer-size as the chosen compiler
|
||||
# Skip if CMAKE_SIZEOF_VOID_P is not defined
|
||||
if(CMAKE_SIZEOF_VOID_P AND (NOT "${PYTHON_SIZEOF_VOID_P}" STREQUAL "${CMAKE_SIZEOF_VOID_P}"))
|
||||
if(PythonLibsNew_FIND_REQUIRED)
|
||||
math(EXPR _PYTHON_BITS "${PYTHON_SIZEOF_VOID_P} * 8")
|
||||
math(EXPR _CMAKE_BITS "${CMAKE_SIZEOF_VOID_P} * 8")
|
||||
message(FATAL_ERROR
|
||||
"Python config failure: Python is ${_PYTHON_BITS}-bit, "
|
||||
"chosen compiler is ${_CMAKE_BITS}-bit")
|
||||
endif()
|
||||
set(PYTHONLIBS_FOUND FALSE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# The built-in FindPython didn't always give the version numbers
|
||||
string(REGEX REPLACE "\\." ";" _PYTHON_VERSION_LIST ${_PYTHON_VERSION_LIST})
|
||||
list(GET _PYTHON_VERSION_LIST 0 PYTHON_VERSION_MAJOR)
|
||||
list(GET _PYTHON_VERSION_LIST 1 PYTHON_VERSION_MINOR)
|
||||
list(GET _PYTHON_VERSION_LIST 2 PYTHON_VERSION_PATCH)
|
||||
|
||||
# Make sure all directory separators are '/'
|
||||
string(REGEX REPLACE "\\\\" "/" PYTHON_PREFIX ${PYTHON_PREFIX})
|
||||
string(REGEX REPLACE "\\\\" "/" PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_DIR})
|
||||
string(REGEX REPLACE "\\\\" "/" PYTHON_SITE_PACKAGES ${PYTHON_SITE_PACKAGES})
|
||||
|
||||
if(CMAKE_HOST_WIN32)
|
||||
set(PYTHON_LIBRARY
|
||||
"${PYTHON_PREFIX}/libs/Python${PYTHON_LIBRARY_SUFFIX}.lib")
|
||||
|
||||
# when run in a venv, PYTHON_PREFIX points to it. But the libraries remain in the
|
||||
# original python installation. They may be found relative to PYTHON_INCLUDE_DIR.
|
||||
if(NOT EXISTS "${PYTHON_LIBRARY}")
|
||||
get_filename_component(_PYTHON_ROOT ${PYTHON_INCLUDE_DIR} DIRECTORY)
|
||||
set(PYTHON_LIBRARY
|
||||
"${_PYTHON_ROOT}/libs/Python${PYTHON_LIBRARY_SUFFIX}.lib")
|
||||
endif()
|
||||
|
||||
# raise an error if the python libs are still not found.
|
||||
if(NOT EXISTS "${PYTHON_LIBRARY}")
|
||||
message(FATAL_ERROR "Python libraries not found")
|
||||
endif()
|
||||
|
||||
else()
|
||||
if(PYTHON_MULTIARCH)
|
||||
set(_PYTHON_LIBS_SEARCH "${PYTHON_LIBDIR}/${PYTHON_MULTIARCH}" "${PYTHON_LIBDIR}")
|
||||
else()
|
||||
set(_PYTHON_LIBS_SEARCH "${PYTHON_LIBDIR}")
|
||||
endif()
|
||||
#message(STATUS "Searching for Python libs in ${_PYTHON_LIBS_SEARCH}")
|
||||
# Probably this needs to be more involved. It would be nice if the config
|
||||
# information the python interpreter itself gave us were more complete.
|
||||
find_library(PYTHON_LIBRARY
|
||||
NAMES "python${PYTHON_LIBRARY_SUFFIX}"
|
||||
PATHS ${_PYTHON_LIBS_SEARCH}
|
||||
NO_DEFAULT_PATH)
|
||||
|
||||
# If all else fails, just set the name/version and let the linker figure out the path.
|
||||
if(NOT PYTHON_LIBRARY)
|
||||
set(PYTHON_LIBRARY python${PYTHON_LIBRARY_SUFFIX})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
PYTHON_LIBRARY
|
||||
PYTHON_INCLUDE_DIR
|
||||
)
|
||||
|
||||
# We use PYTHON_INCLUDE_DIR, PYTHON_LIBRARY and PYTHON_DEBUG_LIBRARY for the
|
||||
# cache entries because they are meant to specify the location of a single
|
||||
# library. We now set the variables listed by the documentation for this
|
||||
# module.
|
||||
SET(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}")
|
||||
SET(PYTHON_LIBRARIES "${PYTHON_LIBRARY}")
|
||||
SET(PYTHON_DEBUG_LIBRARIES "${PYTHON_DEBUG_LIBRARY}")
|
||||
|
||||
find_package_message(PYTHON
|
||||
"Found PythonLibs: ${PYTHON_LIBRARY}"
|
||||
"${PYTHON_EXECUTABLE}${PYTHON_VERSION}")
|
||||
|
||||
set(PYTHONLIBS_FOUND TRUE)
|
||||
@@ -144,31 +144,21 @@ set(mbedtls_src_tls
|
||||
"${MBEDTLS_SOURCE_DIR}/library/ssl_tls13_keys.c"
|
||||
)
|
||||
|
||||
add_library(lief_spdlog INTERFACE)
|
||||
#set_source_files_properties("${MBEDTLS_SOURCE_DIR}/library/bignum.c" PROPERTIES COMPILE_FLAGS -Wno-overlength-strings)
|
||||
|
||||
if(LIEF_EXTERNAL_SPDLOG)
|
||||
find_package(spdlog REQUIRED)
|
||||
list(APPEND CMAKE_MODULE_PATH "${SPDLOG_DIR}/cmake")
|
||||
target_link_libraries(lief_spdlog INTERFACE spdlog::spdlog)
|
||||
get_target_property(SPDLOG_INC_DIR spdlog::spdlog INTERFACE_INCLUDE_DIRECTORIES)
|
||||
target_include_directories(lief_spdlog SYSTEM INTERFACE ${SPDLOG_INC_DIR})
|
||||
else()
|
||||
set(SPDLOG_VERSION 1.8.2)
|
||||
set(SPDLOG_SHA256 SHA256=f0410b12b526065802b40db01304783550d3d20b4b6fe2f8da55f9d08ed2035d)
|
||||
set(SPDLOG_URL "${THIRD_PARTY_DIRECTORY}/spdlog-${SPDLOG_VERSION}.zip" CACHE STRING "URL to the spdlog source")
|
||||
ExternalProject_Add(lief_spdlog_project
|
||||
URL ${SPDLOG_URL}
|
||||
URL_HASH ${SPDLOG_SHA256}
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
UPDATE_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
set(SPDLOG_VERSION 1.8.2)
|
||||
set(SPDLOG_SHA256 SHA256=f0410b12b526065802b40db01304783550d3d20b4b6fe2f8da55f9d08ed2035d)
|
||||
set(SPDLOG_URL "${THIRD_PARTY_DIRECTORY}/spdlog-${SPDLOG_VERSION}.zip" CACHE STRING "URL to the spdlog lib repo")
|
||||
ExternalProject_Add(lief_spdlog
|
||||
URL ${SPDLOG_URL}
|
||||
URL_HASH ${SPDLOG_SHA256}
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
UPDATE_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
|
||||
ExternalProject_get_property(lief_spdlog_project SOURCE_DIR)
|
||||
set(SPDLOG_SOURCE_DIR "${SOURCE_DIR}")
|
||||
add_dependencies(lief_spdlog lief_spdlog_project)
|
||||
target_include_directories(lief_spdlog SYSTEM INTERFACE ${SPDLOG_SOURCE_DIR}/include)
|
||||
endif()
|
||||
ExternalProject_get_property(lief_spdlog SOURCE_DIR)
|
||||
set(SPDLOG_SOURCE_DIR "${SOURCE_DIR}")
|
||||
|
||||
# Fuzzing
|
||||
# ~~~~~~~
|
||||
|
||||
+13
-18
@@ -4,20 +4,19 @@ endif()
|
||||
set(__add_lief_options ON)
|
||||
include(CMakeDependentOption)
|
||||
|
||||
option(LIEF_TESTS "Enable tests" OFF)
|
||||
option(LIEF_DOC "Enable documentation" OFF)
|
||||
option(LIEF_PYTHON_API "Enable Python API" ON)
|
||||
option(LIEF_INSTALL_PYTHON "Install Python bindings" OFF)
|
||||
option(LIEF_C_API "C API" ON)
|
||||
option(LIEF_EXAMPLES "Build LIEF C++ examples" ON)
|
||||
option(LIEF_FORCE32 "Force build LIEF 32 bits version" OFF)
|
||||
option(LIEF_COVERAGE "Perform code coverage" OFF)
|
||||
option(LIEF_USE_CCACHE "Use ccache to speed up compilation" ON)
|
||||
option(LIEF_EXTRA_WARNINGS "Enable extra warning from the compiler" OFF)
|
||||
option(LIEF_LOGGING "Enable logging" ON)
|
||||
option(LIEF_LOGGING_DEBUG "Enable debug logging" ON)
|
||||
option(LIEF_ENABLE_JSON "Enable JSON-related APIs" ON)
|
||||
option(LIEF_FORCE_API_EXPORTS "Force exports of API symbols" OFF)
|
||||
option(LIEF_TESTS "Enable tests" OFF)
|
||||
option(LIEF_DOC "Enable documentation" OFF)
|
||||
option(LIEF_PYTHON_API "Enable Python API" ON)
|
||||
option(LIEF_INSTALL_PYTHON "Install Python bindings" OFF)
|
||||
option(LIEF_C_API "C API" ON)
|
||||
option(LIEF_EXAMPLES "Build LIEF C++ examples" ON)
|
||||
option(LIEF_FORCE32 "Force build LIEF 32 bits version" OFF)
|
||||
option(LIEF_COVERAGE "Perform code coverage" OFF)
|
||||
option(LIEF_USE_CCACHE "Use ccache to speed up compilation" ON)
|
||||
option(LIEF_EXTRA_WARNINGS "Enable extra warning from the compiler" OFF)
|
||||
option(LIEF_LOGGING "Enable logging" ON)
|
||||
option(LIEF_LOGGING_DEBUG "Enable debug logging" ON)
|
||||
option(LIEF_ENABLE_JSON "Enable JSON-related APIs" ON)
|
||||
|
||||
option(LIEF_DISABLE_FROZEN "Disable Frozen even if it is supported" OFF)
|
||||
|
||||
@@ -46,10 +45,6 @@ option(LIEF_PROFILING "Enable performance profiling" OFF)
|
||||
cmake_dependent_option(LIEF_INSTALL_COMPILED_EXAMPLES "Install LIEF Compiled examples" OFF
|
||||
"LIEF_EXAMPLES" OFF)
|
||||
|
||||
# Use a user-provided version of spdlog
|
||||
# It can be useful to reduce compile time
|
||||
option(LIEF_EXTERNAL_SPDLOG OFF)
|
||||
|
||||
set(LIEF_ELF_SUPPORT 0)
|
||||
set(LIEF_PE_SUPPORT 0)
|
||||
set(LIEF_MACHO_SUPPORT 0)
|
||||
|
||||
@@ -60,13 +60,6 @@ Class
|
||||
|
||||
----------
|
||||
|
||||
Field
|
||||
*****
|
||||
|
||||
.. doxygenclass:: LIEF::DEX::Field
|
||||
:project: lief
|
||||
|
||||
----------
|
||||
|
||||
Code Info
|
||||
*********
|
||||
|
||||
@@ -51,18 +51,6 @@ Method
|
||||
|
||||
----------
|
||||
|
||||
Field
|
||||
*****
|
||||
|
||||
.. autoclass:: lief.DEX.Field
|
||||
:members:
|
||||
:inherited-members:
|
||||
:undoc-members:
|
||||
|
||||
|
||||
----------
|
||||
|
||||
|
||||
Class
|
||||
******
|
||||
|
||||
|
||||
@@ -1,68 +1,10 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
0.12.0 - Not Released Yet
|
||||
-------------------------
|
||||
|
||||
:ELF:
|
||||
* :github_user:`Clcanny` improved (see :pr:`507` and :pr:`509`) the reconstruction of the dynamic symbol table
|
||||
by sorting local symbols and non-exported symbols. It fixes the following warning when parsing
|
||||
a modified binary with ``readelf``
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
Warning: local symbol 29 found at index >= .dynsym's sh_info value of 1
|
||||
|
||||
:MachO:
|
||||
* ``LIEF::MachO::Binary::get_symbol`` now returns a pointer (instead of a reference). If the symbol
|
||||
can't be found, it returns a nullptr.
|
||||
* Add API to select a :class:`~lief.MachO.Binary` from a :class:`~lief.MachO.FatBinary` by its achitecture. See:
|
||||
:meth:`lief.MachO.FatBinary.take`.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
fat = lief.MachO.parse("/bin/ls")
|
||||
fit = fat.take(lief.MachO.CPU_TYPES.x86_64)
|
||||
|
||||
* Fix error on property :attr:`lief.MachO.BuildVersion.sdk` (see :issue:`533`)
|
||||
* Handle the `0x0D` binding opcode (see: :issue:`524`)
|
||||
* :github_user:`xhochy` fixed performances issues in the Mach-O parser (see :pr:`579`)
|
||||
|
||||
:DEX:
|
||||
* :github_user:`DanielFi` added support for DEX's fields (see: :pr:`547`)
|
||||
|
||||
:Abstraction:
|
||||
* Abtract binary imagebase for PE, ELF and Mach-O (:attr:`lief.Binary.imagebase`)
|
||||
* Add :meth:`lief.Binary.offset_to_virtual_addres`
|
||||
|
||||
:Compilation:
|
||||
* Enable to use a pre-compiled version of spdlog. This feature aims
|
||||
at improving compilation time when developing on LIEF.
|
||||
|
||||
One can provide path to spdlog install through:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ python ./setup.py --spdlog-dir=path/to/lib/cmake/spdlog [...]
|
||||
# or
|
||||
$ cmake -DLIEF_EXTERNAL_SPDLOG=ON -Dspdlog_DIR=path/to/lib/cmake/spdlog ...
|
||||
|
||||
|
||||
0.11.X - Patch Releases
|
||||
-----------------------
|
||||
|
||||
.. _release-0114:
|
||||
|
||||
0.11.4 - March 09, 2021
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:PE:
|
||||
* Fix missing bound check when computing the authentihash
|
||||
|
||||
.. _release-0113:
|
||||
|
||||
0.11.3 - March 03, 2021
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
--------------------------
|
||||
|
||||
:PE:
|
||||
* Add sanity check on the signature's length that could lead to a ``std::bad_alloc`` exception
|
||||
@@ -71,7 +13,7 @@ Changelog
|
||||
|
||||
|
||||
0.11.2 - February 24, 2021
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
--------------------------
|
||||
|
||||
:PE:
|
||||
* Fix regression in the behavior of the PE section's name. One can now access the full
|
||||
@@ -80,7 +22,7 @@ Changelog
|
||||
.. _release-0111:
|
||||
|
||||
0.11.1 - February 22, 2021
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
--------------------------
|
||||
|
||||
:PE:
|
||||
* :meth:`lief.PE.x509.is_trusted_by` and :meth:`lief.PE.x509.verify` now return
|
||||
@@ -88,6 +30,7 @@ Changelog
|
||||
(see: :issue:`532`)
|
||||
* Fix errors in the computation of the Authentihash
|
||||
|
||||
|
||||
.. _release-0110:
|
||||
|
||||
0.11.0 - January 19, 2021
|
||||
@@ -109,7 +52,7 @@ Changelog
|
||||
* Bug fix in the symbols table reconstruction (ELF)
|
||||
|
||||
:PE:
|
||||
* Enhance PE Authenticode. See `PE Authenticode <https://lief.quarkslab.com/doc/latest/tutorials/13_pe_authenticode.html>`_
|
||||
* Enhance PE Authenticode. See `PE Authenticode <tutorials/13_pe_authenticode.html>`_
|
||||
* :func:`~lief.PE.get_imphash` can now generate the same value as pefile and Virus Total (:issue:`299`)
|
||||
|
||||
.. code-block:: python
|
||||
@@ -473,8 +416,8 @@ Features
|
||||
|
||||
$ readelf -n foo
|
||||
Displaying notes found in: .note.gnu.build-id
|
||||
Owner Data size Description
|
||||
GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
|
||||
Owner Data size Description
|
||||
GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
|
||||
Build ID: ffffffffffffffffffffffffffffffffffffffff
|
||||
|
||||
See commit :commit:`3be9dd0ff58ec68cb8813e01d6798c16b42dac22` for more details
|
||||
|
||||
@@ -296,7 +296,7 @@ pass :class:`lief.PE.Signature.VERIFICATION_CHECKS` flags to customize its behav
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
pe.verify_signature(lief.PE.Signature.VERIFICATION_CHECKS.HASH_ONLY)
|
||||
pe.verify_signature(lief.PE.VERIFICATION_CHECKS.HASH_ONLY)
|
||||
|
||||
|
||||
:Lifetime Signing:
|
||||
@@ -306,8 +306,8 @@ pass :class:`lief.PE.Signature.VERIFICATION_CHECKS` flags to customize its behav
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
pe.verify_signature(lief.PE.Signature.VERIFICATION_CHECKS.LIFETIME_SIGNING)
|
||||
signature.check(lief.PE.Signature.VERIFICATION_CHECKS.LIFETIME_SIGNING)
|
||||
pe.verify_signature(lief.PE.VERIFICATION_CHECKS.LIFETIME_SIGNING)
|
||||
signature.check(lief.PE.VERIFICATION_CHECKS.LIFETIME_SIGNING)
|
||||
|
||||
|
||||
:Skip Cerificate Check Time:
|
||||
@@ -319,8 +319,8 @@ pass :class:`lief.PE.Signature.VERIFICATION_CHECKS` flags to customize its behav
|
||||
|
||||
# Returns lief.PE.Signature.VERIFICATION_FLAGS.OK even though
|
||||
# the certificates expired
|
||||
pe.verify_signature(lief.PE.Signature.VERIFICATION_CHECKS.SKIP_CERT_TIME)
|
||||
signature.check(lief.PE.Signature.VERIFICATION_CHECKS.SKIP_CERT_TIME)
|
||||
pe.verify_signature(lief.PE.VERIFICATION_CHECKS.SKIP_CERT_TIME)
|
||||
signature.check(lief.PE.VERIFICATION_CHECKS.SKIP_CERT_TIME)
|
||||
|
||||
.. note::
|
||||
|
||||
|
||||
@@ -79,18 +79,6 @@ def print_classes(dexfile):
|
||||
for cls in classes:
|
||||
print(cls)
|
||||
|
||||
@exceptions_handler(Exception)
|
||||
def print_fields(dexfile):
|
||||
format_str = "{:<33} {:<30}"
|
||||
format_hex = "{:<33} 0x{:<28x}"
|
||||
format_dec = "{:<33} {:<30d}"
|
||||
|
||||
fields = dexfile.fields
|
||||
|
||||
print("== Fields ==")
|
||||
for f in fields:
|
||||
print(f)
|
||||
|
||||
@exceptions_handler(Exception)
|
||||
def print_methods(dexfile):
|
||||
format_str = "{:<33} {:<30}"
|
||||
@@ -141,10 +129,6 @@ def main():
|
||||
action='store_true', dest='show_classes',
|
||||
help='Display classes')
|
||||
|
||||
parser.add_argument('-f', '--fields',
|
||||
action='store_true', dest='show_fields',
|
||||
help='Display Fields')
|
||||
|
||||
parser.add_argument('-m', '--methods',
|
||||
action='store_true', dest='show_methods',
|
||||
help='Display Methods')
|
||||
@@ -223,9 +207,6 @@ def main():
|
||||
if (args.show_classes or args.show_all) and len(dexfile.classes) > 0:
|
||||
print_classes(dexfile)
|
||||
|
||||
if (args.show_fields or args.show_all) and len(dexfile.fields) > 0:
|
||||
print_fields(dexfile)
|
||||
|
||||
if (args.show_methods or args.show_all) and len(dexfile.methods) > 0:
|
||||
print_methods(dexfile)
|
||||
|
||||
|
||||
@@ -259,19 +259,7 @@ def print_relocations(binary, relocations):
|
||||
elif binary.header.machine_type == ELF.ARCH.AARCH64:
|
||||
type = str(ELF.RELOCATION_AARCH64(relocation.type))
|
||||
|
||||
symbol_name = ""
|
||||
if relocation.has_symbol:
|
||||
symbol: lief.ELF.Symbol = relocation.symbol
|
||||
if len(symbol.name) > 0:
|
||||
symbol_name = symbol.name
|
||||
elif symbol.type == lief.ELF.SYMBOL_TYPES.SECTION:
|
||||
shndx = symbol.shndx
|
||||
sections = binary.sections
|
||||
if 0 < shndx and shndx < len(sections):
|
||||
symbol_name = sections[shndx].name + " + " + hex(relocation.addend)
|
||||
else:
|
||||
symbol_name = "<section #{}>".format(shndx)
|
||||
|
||||
symbol_name = str(relocation.symbol.name) if relocation.has_symbol else ""
|
||||
|
||||
print(f_value.format(
|
||||
relocation.address,
|
||||
|
||||
@@ -26,15 +26,12 @@
|
||||
#include "LIEF/ART/File.hpp"
|
||||
|
||||
|
||||
struct Profiler;
|
||||
|
||||
namespace LIEF {
|
||||
namespace ART {
|
||||
|
||||
//! @brief Class which parse an ART file and transform into a ART::File object
|
||||
class LIEF_API Parser {
|
||||
public:
|
||||
friend struct ::Profiler;
|
||||
static std::unique_ptr<File> parse(const std::string& file);
|
||||
static std::unique_ptr<File> parse(const std::vector<uint8_t>& data, const std::string& name = "");
|
||||
|
||||
|
||||
@@ -144,18 +144,9 @@ class LIEF_API Binary : public Object {
|
||||
//! @brief Check if the binary uses ``NX`` protection
|
||||
virtual bool has_nx(void) const = 0;
|
||||
|
||||
//! Default image base address if the ASLR is not enabled.
|
||||
virtual uint64_t imagebase() const = 0;
|
||||
|
||||
//! Constructor functions that are called prior any other functions
|
||||
virtual LIEF::Binary::functions_t ctor_functions(void) const = 0;
|
||||
|
||||
//! Convert the given offset into a virtual address.
|
||||
//!
|
||||
//! @param[in] offset The offset to convert.
|
||||
//! @param[in] slide If not 0, it will replace the default base address (if any)
|
||||
virtual uint64_t offset_to_virtual_address(uint64_t offset, uint64_t slide = 0) const = 0;
|
||||
|
||||
virtual std::ostream& print(std::ostream& os) const;
|
||||
|
||||
virtual void write(const std::string& name) = 0;
|
||||
|
||||
@@ -22,13 +22,10 @@
|
||||
|
||||
#include "LIEF/visibility.h"
|
||||
|
||||
struct Profiler;
|
||||
|
||||
namespace LIEF {
|
||||
class Binary;
|
||||
class LIEF_API Parser {
|
||||
public:
|
||||
friend struct ::Profiler;
|
||||
//! @brief Construct an LIEF::Binary from the given filename
|
||||
//!
|
||||
//! @warning If the target file is a FAT Mach0, it will
|
||||
|
||||
@@ -32,18 +32,10 @@ struct mbedtls_x509_time;
|
||||
namespace LIEF {
|
||||
class BinaryStream {
|
||||
public:
|
||||
enum class STREAM_TYPE {
|
||||
UNKNOWN = 0,
|
||||
FILE,
|
||||
MEMORY,
|
||||
};
|
||||
|
||||
BinaryStream(void);
|
||||
virtual ~BinaryStream();
|
||||
virtual uint64_t size(void) const = 0;
|
||||
|
||||
virtual STREAM_TYPE type() const = 0;
|
||||
|
||||
uint64_t read_uleb128(void) const;
|
||||
uint64_t read_sleb128(void) const;
|
||||
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
/* Copyright 2017 - 2021 R. Thomas
|
||||
* Copyright 2017 - 2021 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_MEMORY_STREAM_H
|
||||
#define LIEF_MEMORY_STREAM_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "LIEF/BinaryStream/BinaryStream.hpp"
|
||||
|
||||
namespace LIEF {
|
||||
class Binary;
|
||||
class MemoryStream : public BinaryStream {
|
||||
public:
|
||||
MemoryStream() = delete;
|
||||
MemoryStream(uintptr_t base_address);
|
||||
MemoryStream(uintptr_t base_address, uint64_t size);
|
||||
|
||||
inline uintptr_t base_address() const {
|
||||
return this->baseaddr_;
|
||||
}
|
||||
|
||||
inline uint64_t end() const {
|
||||
return this->baseaddr_ + this->size_;
|
||||
}
|
||||
|
||||
inline STREAM_TYPE type() const override {
|
||||
return STREAM_TYPE::MEMORY;
|
||||
}
|
||||
|
||||
inline void binary(Binary& bin) {
|
||||
this->binary_ = &bin;
|
||||
}
|
||||
|
||||
inline Binary* binary() {
|
||||
return this->binary_;
|
||||
}
|
||||
|
||||
virtual uint64_t size(void) const override;
|
||||
|
||||
virtual result<size_t> asn1_read_tag(int tag) override;
|
||||
virtual result<size_t> asn1_read_len() override;
|
||||
result<size_t> asn1_peek_len();
|
||||
virtual result<std::string> asn1_read_alg() override;
|
||||
virtual result<std::string> asn1_read_oid() override;
|
||||
virtual result<int32_t> asn1_read_int() override;
|
||||
virtual result<std::vector<uint8_t>> asn1_read_bitstring() override;
|
||||
virtual result<std::vector<uint8_t>> asn1_read_octet_string() override;
|
||||
virtual result<std::unique_ptr<mbedtls_x509_crt>> asn1_read_cert() override;
|
||||
virtual result<std::string> x509_read_names() override;
|
||||
virtual result<std::vector<uint8_t>> x509_read_serial() override;
|
||||
virtual result<std::unique_ptr<mbedtls_x509_time>> x509_read_time() override;
|
||||
|
||||
virtual ~MemoryStream();
|
||||
|
||||
|
||||
protected:
|
||||
virtual const void* read_at(uint64_t offset, uint64_t size, bool throw_error = true) const override;
|
||||
uintptr_t baseaddr_ = 0;
|
||||
uint64_t size_ = 0;
|
||||
Binary* binary_ = nullptr;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -27,10 +27,6 @@ class VectorStream : public BinaryStream {
|
||||
VectorStream(const std::string& filename);
|
||||
VectorStream(const std::vector<uint8_t>& data);
|
||||
|
||||
inline STREAM_TYPE type() const override {
|
||||
return STREAM_TYPE::FILE;
|
||||
}
|
||||
|
||||
virtual uint64_t size(void) const override;
|
||||
|
||||
const std::vector<uint8_t>& content(void) const;
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "LIEF/DEX/Class.hpp"
|
||||
#include "LIEF/DEX/Header.hpp"
|
||||
#include "LIEF/DEX/Method.hpp"
|
||||
#include "LIEF/DEX/Field.hpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "LIEF/DEX/type_traits.hpp"
|
||||
#include "LIEF/DEX/Structures.hpp"
|
||||
#include "LIEF/DEX/Method.hpp"
|
||||
#include "LIEF/DEX/Field.hpp"
|
||||
|
||||
namespace LIEF {
|
||||
namespace DEX {
|
||||
@@ -85,14 +84,6 @@ class LIEF_API Class : public Object {
|
||||
it_methods methods(const std::string& name);
|
||||
it_const_methods methods(const std::string& name) const;
|
||||
|
||||
//! Fields implemented in this class
|
||||
it_const_fields fields(void) const;
|
||||
it_fields fields(void);
|
||||
|
||||
//! Return Fields having the given name
|
||||
it_fields fields(const std::string& name);
|
||||
it_const_fields fields(const std::string& name) const;
|
||||
|
||||
//! De-optimize information
|
||||
dex2dex_class_info_t dex2dex_info(void) const;
|
||||
|
||||
@@ -110,13 +101,11 @@ class LIEF_API Class : public Object {
|
||||
|
||||
private:
|
||||
methods_t method_from_name(const std::string& name) const;
|
||||
fields_t field_from_name(const std::string& name) const;
|
||||
|
||||
std::string fullname_;
|
||||
uint32_t access_flags_;
|
||||
Class* parent_{nullptr};
|
||||
methods_t methods_;
|
||||
fields_t fields_;
|
||||
std::string source_filename_;
|
||||
|
||||
uint32_t original_index_;
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
#ifndef LIEF_DEX_FIELD_H_
|
||||
#define LIEF_DEX_FIELD_H_
|
||||
|
||||
#include "LIEF/DEX/type_traits.hpp"
|
||||
#include "LIEF/DEX/Structures.hpp"
|
||||
|
||||
#include "LIEF/visibility.h"
|
||||
#include "LIEF/Object.hpp"
|
||||
|
||||
#include "LIEF/DEX/Type.hpp"
|
||||
|
||||
namespace LIEF {
|
||||
namespace DEX {
|
||||
class Parser;
|
||||
class Class;
|
||||
|
||||
class LIEF_API Field : public Object {
|
||||
friend class Parser;
|
||||
public:
|
||||
using access_flags_list_t = std::vector<ACCESS_FLAGS>;
|
||||
|
||||
public:
|
||||
Field(void);
|
||||
Field(const std::string& name, Class* parent = nullptr);
|
||||
|
||||
Field(const Field&);
|
||||
Field& operator=(const Field&);
|
||||
|
||||
//! Name of the Field
|
||||
const std::string& name(void) const;
|
||||
|
||||
//! True if a class is associated with this field
|
||||
bool has_class(void) const;
|
||||
|
||||
//! Class associated with this Field
|
||||
const Class& cls(void) const;
|
||||
Class& cls(void);
|
||||
|
||||
//! Index in the DEX Fields pool
|
||||
size_t index(void) const;
|
||||
|
||||
//! True if this field is a static one.
|
||||
bool is_static(void) const;
|
||||
|
||||
//! Field's prototype
|
||||
const Type& type(void) const;
|
||||
Type& type(void);
|
||||
|
||||
virtual void accept(Visitor& visitor) const override;
|
||||
|
||||
bool has(ACCESS_FLAGS f) const;
|
||||
|
||||
access_flags_list_t access_flags(void) const;
|
||||
|
||||
bool operator==(const Field& rhs) const;
|
||||
bool operator!=(const Field& rhs) const;
|
||||
|
||||
LIEF_API friend std::ostream& operator<<(std::ostream& os, const Field& mtd);
|
||||
|
||||
virtual ~Field(void);
|
||||
|
||||
private:
|
||||
void set_static(bool v);
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
Class* parent_{nullptr};
|
||||
Type* type_{nullptr};
|
||||
uint32_t access_flags_ = 0;
|
||||
uint32_t original_index_ = -1u;
|
||||
bool is_static_ = false;
|
||||
|
||||
};
|
||||
|
||||
} // Namespace DEX
|
||||
} // Namespace LIEF
|
||||
#endif
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "LIEF/DEX/Header.hpp"
|
||||
#include "LIEF/DEX/Class.hpp"
|
||||
#include "LIEF/DEX/Method.hpp"
|
||||
#include "LIEF/DEX/Field.hpp"
|
||||
#include "LIEF/DEX/Type.hpp"
|
||||
#include "LIEF/DEX/Prototype.hpp"
|
||||
#include "LIEF/DEX/instructions.hpp"
|
||||
@@ -91,10 +90,6 @@ class LIEF_API File : public Object {
|
||||
it_const_methods methods(void) const;
|
||||
it_methods methods(void);
|
||||
|
||||
//! **All** Fields used in this DEX
|
||||
it_const_fields fields(void) const;
|
||||
it_fields fields(void);
|
||||
|
||||
//! String pool
|
||||
it_const_strings strings(void) const;
|
||||
it_strings strings(void);
|
||||
@@ -142,7 +137,6 @@ class LIEF_API File : public Object {
|
||||
Header header_;
|
||||
classes_t classes_;
|
||||
methods_t methods_;
|
||||
fields_t fields_;
|
||||
strings_t strings_;
|
||||
types_t types_;
|
||||
prototypes_t prototypes_;
|
||||
|
||||
@@ -24,18 +24,15 @@
|
||||
|
||||
#include "LIEF/DEX/File.hpp"
|
||||
|
||||
struct Profiler;
|
||||
|
||||
namespace LIEF {
|
||||
namespace DEX {
|
||||
class Class;
|
||||
class Method;
|
||||
class Field;
|
||||
|
||||
//! @brief Class which parse a DEX file and transform into a DEX::File object
|
||||
class LIEF_API Parser {
|
||||
public:
|
||||
friend struct ::Profiler;
|
||||
static std::unique_ptr<File> parse(const std::string& file);
|
||||
static std::unique_ptr<File> parse(const std::vector<uint8_t>& data, const std::string& name = "");
|
||||
|
||||
@@ -80,9 +77,6 @@ class LIEF_API Parser {
|
||||
template<typename DEX_T>
|
||||
void parse_class_data(uint32_t offset, Class* cls);
|
||||
|
||||
template<typename DEX_T>
|
||||
void parse_field(size_t index, Class* cls, bool is_static);
|
||||
|
||||
template<typename DEX_T>
|
||||
void parse_method(size_t index, Class* cls, bool is_virtual);
|
||||
|
||||
@@ -93,8 +87,6 @@ class LIEF_API Parser {
|
||||
|
||||
void resolve_external_methods(void);
|
||||
|
||||
void resolve_external_fields(void);
|
||||
|
||||
void resolve_types(void);
|
||||
|
||||
LIEF::DEX::File* file_;
|
||||
@@ -107,10 +99,6 @@ class LIEF_API Parser {
|
||||
// The key is the Class name in which the method is defined
|
||||
std::unordered_multimap<std::string, Method*> class_method_map_;
|
||||
|
||||
// Map of field/class relationship when parsing fields ('parse_fields')
|
||||
// The key is the Class name in which the field is defined
|
||||
std::unordered_multimap<std::string, Field*> class_field_map_;
|
||||
|
||||
std::unordered_multimap<std::string, Type*> class_type_map_;
|
||||
|
||||
std::unique_ptr<VectorStream> stream_;
|
||||
|
||||
@@ -35,7 +35,6 @@ class LIEF_API Hash : public LIEF::Hash {
|
||||
virtual void visit(const File& file) override;
|
||||
virtual void visit(const Header& header) override;
|
||||
virtual void visit(const Class& cls) override;
|
||||
virtual void visit(const Field& field) override;
|
||||
virtual void visit(const Method& method) override;
|
||||
virtual void visit(const CodeInfo& code_info) override;
|
||||
virtual void visit(const Type& type) override;
|
||||
|
||||
@@ -40,7 +40,6 @@ class LIEF_API JsonVisitor : public LIEF::JsonVisitor {
|
||||
virtual void visit(const Header& header) override;
|
||||
virtual void visit(const Class& cls) override;
|
||||
virtual void visit(const Method& method) override;
|
||||
virtual void visit(const Field& field) override;
|
||||
virtual void visit(const CodeInfo& codeinfo) override;
|
||||
virtual void visit(const Type& type) override;
|
||||
virtual void visit(const Prototype& type) override;
|
||||
|
||||
@@ -27,7 +27,6 @@ namespace DEX {
|
||||
class File;
|
||||
class Class;
|
||||
class Method;
|
||||
class Field;
|
||||
class Type;
|
||||
class Prototype;
|
||||
|
||||
@@ -48,10 +47,6 @@ using methods_t = std::vector<Method*>;
|
||||
using it_methods = ref_iterator<methods_t>;
|
||||
using it_const_methods = const_ref_iterator<const methods_t>;
|
||||
|
||||
using fields_t = std::vector<Field*>;
|
||||
using it_fields = ref_iterator<fields_t>;
|
||||
using it_const_fields = const_ref_iterator<const fields_t>;
|
||||
|
||||
using strings_t = std::vector<std::string*>;
|
||||
using it_strings = ref_iterator<strings_t>;
|
||||
using it_const_strings = const_ref_iterator<const strings_t>;
|
||||
|
||||
@@ -227,7 +227,7 @@ class LIEF_API Binary : public LIEF::Binary {
|
||||
//!
|
||||
//! To compute the image base, we look for the PT_PHDR segment header (phdr),
|
||||
//! and we return phdr->p_vaddr - phdr->p_offset
|
||||
uint64_t imagebase(void) const override;
|
||||
uint64_t imagebase(void) const;
|
||||
|
||||
//! Return the size of the mapped binary
|
||||
uint64_t virtual_size(void) const;
|
||||
@@ -401,12 +401,6 @@ class LIEF_API Binary : public LIEF::Binary {
|
||||
//! Convert a virtual address to an offset in the file
|
||||
uint64_t virtual_address_to_offset(uint64_t virtual_address) const;
|
||||
|
||||
//! Convert the given offset into a virtual address.
|
||||
//!
|
||||
//! @param[in] offset The offset to convert.
|
||||
//! @param[in] slide If not 0, it will replace the default base address (if any)
|
||||
uint64_t offset_to_virtual_address(uint64_t offset, uint64_t slide = 0) const override;
|
||||
|
||||
//! Check if the binary has been compiled with `-fpie -pie` flags
|
||||
//!
|
||||
//! To do so we check if there is a `PT_INTERP` segment and if
|
||||
|
||||
@@ -27,8 +27,6 @@
|
||||
|
||||
#include "LIEF/ELF/enums.hpp"
|
||||
|
||||
struct Profiler;
|
||||
|
||||
namespace LIEF {
|
||||
namespace ELF {
|
||||
class Binary;
|
||||
@@ -41,7 +39,6 @@ class Section;
|
||||
//! @brief Class which take a ELF::Binary object and reconstruct a valid binary
|
||||
class LIEF_API Builder {
|
||||
public:
|
||||
friend struct ::Profiler;
|
||||
Builder(Binary *binary);
|
||||
|
||||
Builder(void) = delete;
|
||||
@@ -95,9 +92,7 @@ class LIEF_API Builder {
|
||||
void build_symbol_hash(void);
|
||||
|
||||
template<typename ELF_T>
|
||||
void build_symbol_gnuhash(uint32_t new_symndx);
|
||||
|
||||
uint32_t sort_dynamic_symbols(void);
|
||||
void build_symbol_gnuhash(void);
|
||||
|
||||
void build_empty_symbol_gnuhash(void);
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "LIEF/ELF/DataHandler/Node.hpp"
|
||||
|
||||
namespace LIEF {
|
||||
class BinaryStream;
|
||||
namespace ELF {
|
||||
namespace DataHandler {
|
||||
|
||||
@@ -32,7 +31,6 @@ class LIEF_API Handler {
|
||||
static constexpr size_t MAX_SIZE = 1_GB;
|
||||
Handler(const std::vector<uint8_t>& content);
|
||||
Handler(std::vector<uint8_t>&& content);
|
||||
Handler(BinaryStream& stream);
|
||||
~Handler(void);
|
||||
|
||||
Handler& operator=(const Handler&);
|
||||
|
||||
@@ -23,10 +23,9 @@
|
||||
|
||||
#include "LIEF/ELF/enums.hpp"
|
||||
|
||||
struct Profiler;
|
||||
|
||||
namespace LIEF {
|
||||
class BinaryStream;
|
||||
class VectorStream;
|
||||
|
||||
namespace OAT {
|
||||
class Parser;
|
||||
@@ -41,7 +40,6 @@ class Binary;
|
||||
class LIEF_API Parser : public LIEF::Parser {
|
||||
friend class OAT::Parser;
|
||||
public:
|
||||
friend struct ::Profiler;
|
||||
|
||||
static constexpr uint32_t NB_MAX_SYMBOLS = 1000000;
|
||||
static constexpr uint32_t DELTA_NB_SYMBOLS = 3000;
|
||||
@@ -227,7 +225,7 @@ class LIEF_API Parser : public LIEF::Parser {
|
||||
template<typename ELF_T, typename REL_T>
|
||||
uint32_t max_relocation_index(uint64_t relocations_offset, uint64_t size) const;
|
||||
|
||||
std::unique_ptr<BinaryStream> stream_;
|
||||
std::unique_ptr<VectorStream> stream_;
|
||||
Binary* binary_{nullptr};
|
||||
ELF_CLASS type_;
|
||||
DYNSYM_COUNT_METHODS count_mtd_;
|
||||
|
||||
@@ -221,7 +221,6 @@ enum _LIEF_EN(ARCH) {
|
||||
_LIEF_EI(EM_NORC) = 218, /**< Nanoradio Optimized RISC */
|
||||
_LIEF_EI(EM_CSR_KALIMBA) = 219, /**< CSR Kalimba architecture family */
|
||||
_LIEF_EI(EM_AMDGPU) = 224, /**< AMD GPU architecture */
|
||||
_LIEF_EI(EM_RISCV) = 243, /**< RISC-V */
|
||||
_LIEF_EI(EM_BPF) = 247 /**< eBPF Filter */
|
||||
};
|
||||
|
||||
|
||||
@@ -230,7 +230,6 @@
|
||||
#undef EM_NORC
|
||||
#undef EM_CSR_KALIMBA
|
||||
#undef EM_AMDGPU
|
||||
#undef EM_RISCV
|
||||
#undef EM_BPF
|
||||
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#define LIEF_MACHO_BINARY_H_
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "LIEF/types.hpp"
|
||||
#include "LIEF/visibility.h"
|
||||
@@ -84,10 +83,9 @@ class LIEF_API Binary : public LIEF::Binary {
|
||||
//! If a symbol with the given name exists
|
||||
bool has_symbol(const std::string& name) const;
|
||||
|
||||
//! Return Symbol from the given name. If the symbol does not
|
||||
//! exists, it returns a null pointer
|
||||
const Symbol* get_symbol(const std::string& name) const;
|
||||
Symbol* get_symbol(const std::string& name);
|
||||
//! Return Symbol from the given name
|
||||
const Symbol& get_symbol(const std::string& name) const;
|
||||
Symbol& get_symbol(const std::string& name);
|
||||
|
||||
//! Check if the given symbol is an exported one
|
||||
static bool is_exported(const Symbol& symbol);
|
||||
@@ -180,7 +178,7 @@ class LIEF_API Binary : public LIEF::Binary {
|
||||
bool disable_pie(void);
|
||||
|
||||
//! Return binary's imagebase. ``0`` if not relevant
|
||||
uint64_t imagebase(void) const override;
|
||||
uint64_t imagebase(void) const;
|
||||
|
||||
//! Size of the binary in memory when mapped
|
||||
uint64_t virtual_size(void) const;
|
||||
@@ -238,12 +236,6 @@ class LIEF_API Binary : public LIEF::Binary {
|
||||
//! Convert a virtual address to an offset in the file
|
||||
uint64_t virtual_address_to_offset(uint64_t virtualAddress) const;
|
||||
|
||||
//! Convert the given offset into a virtual address.
|
||||
//!
|
||||
//! @param[in] offset The offset to convert.
|
||||
//! @param[in] slide If not 0, it will replace the default base address (if any)
|
||||
uint64_t offset_to_virtual_address(uint64_t offset, uint64_t slide = 0) const override;
|
||||
|
||||
// Return binary's @link MachO::SegmentCommand segment command
|
||||
// which hold the offset
|
||||
SegmentCommand* segment_from_offset(uint64_t offset);
|
||||
@@ -474,10 +466,6 @@ class LIEF_API Binary : public LIEF::Binary {
|
||||
|
||||
void shift_command(size_t width, size_t from_offset);
|
||||
|
||||
//! Insert Segment command in the cache field (segments_)
|
||||
//! and keep a consistent state of the indexes.
|
||||
size_t add_cached_segment(SegmentCommand& segment);
|
||||
|
||||
template<class T>
|
||||
LIEF_LOCAL void patch_relocation(Relocation& relocation, uint64_t from, uint64_t shift);
|
||||
|
||||
@@ -501,23 +489,15 @@ class LIEF_API Binary : public LIEF::Binary {
|
||||
return this->is64_ ? sizeof(uint64_t) : sizeof(uint32_t);
|
||||
}
|
||||
|
||||
bool is64_;
|
||||
Header header_;
|
||||
commands_t commands_;
|
||||
symbols_t symbols_;
|
||||
libraries_t libraries_;
|
||||
sections_t sections_;
|
||||
segments_t segments_;
|
||||
bool is64_;
|
||||
Header header_;
|
||||
commands_t commands_;
|
||||
symbols_t symbols_;
|
||||
|
||||
// Cached relocations from segment / sections
|
||||
mutable relocations_t relocations_;
|
||||
int32_t available_command_space_ = 0;
|
||||
|
||||
// This is used to improve performances of
|
||||
// offset_to_virtual_address
|
||||
std::map<uint64_t, SegmentCommand*> offset_seg_;
|
||||
|
||||
|
||||
protected:
|
||||
uint64_t fat_offset_ = 0;
|
||||
};
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include "LIEF/types.hpp"
|
||||
#include "LIEF/visibility.h"
|
||||
@@ -32,7 +31,7 @@
|
||||
#include "LIEF/MachO/type_traits.hpp"
|
||||
|
||||
namespace LIEF {
|
||||
class BinaryStream;
|
||||
class VectorStream;
|
||||
|
||||
namespace MachO {
|
||||
class Section;
|
||||
@@ -62,7 +61,7 @@ class LIEF_API BinaryParser : public LIEF::Parser {
|
||||
Binary* get_binary(void);
|
||||
|
||||
private:
|
||||
BinaryParser(std::unique_ptr<BinaryStream>&& stream, uint64_t fat_offset = 0, const ParserConfig& conf = ParserConfig::deep());
|
||||
BinaryParser(std::unique_ptr<VectorStream>&& stream, uint64_t fat_offset = 0, const ParserConfig& conf = ParserConfig::deep());
|
||||
|
||||
void init(void);
|
||||
|
||||
@@ -116,7 +115,7 @@ class LIEF_API BinaryParser : public LIEF::Parser {
|
||||
|
||||
|
||||
template<class MACHO_T>
|
||||
void do_rebase(uint8_t type, uint8_t segment_idx, uint64_t segment_address, const it_segments& segments);
|
||||
void do_rebase(uint8_t type, uint8_t segment_idx, uint64_t segment_address);
|
||||
|
||||
// Exports
|
||||
// -------
|
||||
@@ -124,14 +123,12 @@ class LIEF_API BinaryParser : public LIEF::Parser {
|
||||
|
||||
void parse_export_trie(uint64_t start, uint64_t end, const std::string& prefix);
|
||||
|
||||
std::unique_ptr<BinaryStream> stream_;
|
||||
Binary* binary_{nullptr};
|
||||
MACHO_TYPES type_;
|
||||
bool is64_;
|
||||
ParserConfig config_;
|
||||
std::set<uint64_t> visited_;
|
||||
std::map<std::string, Symbol*> memoized_symbols_;
|
||||
std::map<uint64_t, Symbol*> memoized_symbols_by_address_;
|
||||
std::unique_ptr<VectorStream> stream_;
|
||||
Binary* binary_{nullptr};
|
||||
MACHO_TYPES type_;
|
||||
bool is64_;
|
||||
ParserConfig config_;
|
||||
std::set<uint64_t> visited_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -20,15 +20,11 @@
|
||||
#include <vector>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "LIEF/visibility.h"
|
||||
#include "LIEF/exception.hpp"
|
||||
#include "LIEF/iostream.hpp"
|
||||
|
||||
struct Profiler;
|
||||
|
||||
namespace LIEF {
|
||||
namespace MachO {
|
||||
class Binary;
|
||||
@@ -52,7 +48,6 @@ class BuildVersion;
|
||||
|
||||
class LIEF_API Builder {
|
||||
public:
|
||||
friend struct ::Profiler;
|
||||
static void write(Binary *binary, const std::string& filename);
|
||||
static void write(FatBinary* fatbinary, const std::string& filename);
|
||||
|
||||
@@ -74,11 +69,6 @@ class LIEF_API Builder {
|
||||
template<typename T>
|
||||
void build(void);
|
||||
|
||||
template<typename T, typename HANDLER>
|
||||
std::vector<std::string> optimize(const HANDLER& e,
|
||||
std::function<std::string(const typename HANDLER::value_type)> getter,
|
||||
std::unordered_map<std::string, size_t> *of_map_p=nullptr);
|
||||
|
||||
void build_fat(void);
|
||||
void build_fat_header(void);
|
||||
void build_header(void);
|
||||
|
||||
@@ -47,12 +47,6 @@ class LIEF_API DyldInfo : public LoadCommand {
|
||||
//! @brief Tuple of ``offset`` and ``size``
|
||||
using info_t = std::pair<uint32_t, uint32_t>;
|
||||
|
||||
enum class BINDING_ENCODING_VERSION {
|
||||
UNKNOWN = 0,
|
||||
V1,
|
||||
V2
|
||||
};
|
||||
|
||||
DyldInfo(void);
|
||||
DyldInfo(const dyld_info_command *dyld_info_cmd);
|
||||
|
||||
@@ -253,16 +247,13 @@ class LIEF_API DyldInfo : public LoadCommand {
|
||||
|
||||
void show_trie(std::ostream& output, std::string output_prefix, VectorStream& stream, uint64_t start, uint64_t end, const std::string& prefix) const;
|
||||
|
||||
LIEF_LOCAL DyldInfo& update_standard_bindings(const bind_container_t& bindings);
|
||||
LIEF_LOCAL DyldInfo& update_standard_bindings_v1(const bind_container_t& bindings);
|
||||
LIEF_LOCAL DyldInfo& update_standard_bindings_v2(const bind_container_t& bindings, std::vector<RelocationDyld*> rebases);
|
||||
DyldInfo& update_standard_bindings(const bind_container_t& bindings);
|
||||
DyldInfo& update_weak_bindings(const bind_container_t& bindings);
|
||||
DyldInfo& update_lazy_bindings(const bind_container_t& bindings);
|
||||
|
||||
LIEF_LOCAL DyldInfo& update_weak_bindings(const bind_container_t& bindings);
|
||||
LIEF_LOCAL DyldInfo& update_lazy_bindings(const bind_container_t& bindings);
|
||||
|
||||
LIEF_LOCAL DyldInfo& update_rebase_info(void);
|
||||
LIEF_LOCAL DyldInfo& update_binding_info(void);
|
||||
LIEF_LOCAL DyldInfo& update_export_trie(void);
|
||||
DyldInfo& update_rebase_info(void);
|
||||
DyldInfo& update_binding_info(void);
|
||||
DyldInfo& update_export_trie(void);
|
||||
|
||||
|
||||
info_t rebase_;
|
||||
@@ -283,9 +274,7 @@ class LIEF_API DyldInfo : public LoadCommand {
|
||||
export_info_t export_info_;
|
||||
binding_info_t binding_info_;
|
||||
|
||||
BINDING_ENCODING_VERSION binding_encoding_version_ = BINDING_ENCODING_VERSION::UNKNOWN;
|
||||
|
||||
Binary* binary_ = nullptr;
|
||||
Binary* binary_{nullptr};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -46,7 +46,6 @@ LIEF_API const char* to_string(BINDING_CLASS e);
|
||||
LIEF_API const char* to_string(REBASE_OPCODES e);
|
||||
LIEF_API const char* to_string(BIND_TYPES e);
|
||||
LIEF_API const char* to_string(BIND_SPECIAL_DYLIB e);
|
||||
LIEF_API const char* to_string(BIND_SUBOPCODE_THREADED e);
|
||||
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);
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "LIEF/types.hpp"
|
||||
#include "LIEF/visibility.h"
|
||||
|
||||
#include "LIEF/MachO/enums.hpp"
|
||||
#include "LIEF/MachO/type_traits.hpp"
|
||||
|
||||
namespace LIEF {
|
||||
@@ -67,13 +66,9 @@ class LIEF_API FatBinary {
|
||||
//! Extract a MachO::Binary object. Gives ownership to the caller, and
|
||||
//! remove it from this FatBinary object.
|
||||
//!
|
||||
//! @warning: this invalidates any previously hold iterator!
|
||||
//! @warning: this invalidates any previously hold iterator!
|
||||
std::unique_ptr<Binary> take(size_t index);
|
||||
|
||||
//! Take the underlying MachO::Binary that matches the given architecture
|
||||
//! If no binary with the architecture can be found, return a nullptr
|
||||
std::unique_ptr<Binary> take(CPU_TYPES cpu);
|
||||
|
||||
//! Reconstruct the Fat binary object and write it in `filename`
|
||||
//! @param filename Path to write the reconstructed binary
|
||||
void write(const std::string& filename);
|
||||
|
||||
@@ -26,10 +26,8 @@
|
||||
|
||||
#include "LIEF/MachO/ParserConfig.hpp"
|
||||
|
||||
struct Profiler;
|
||||
|
||||
namespace LIEF {
|
||||
class BinaryStream;
|
||||
class VectorStream;
|
||||
|
||||
namespace MachO {
|
||||
class Binary;
|
||||
@@ -37,7 +35,6 @@ class FatBinary;
|
||||
|
||||
class LIEF_API Parser : public LIEF::Parser {
|
||||
public:
|
||||
friend struct ::Profiler;
|
||||
Parser& operator=(const Parser& copy) = delete;
|
||||
Parser(const Parser& copy) = delete;
|
||||
|
||||
@@ -54,7 +51,7 @@ class LIEF_API Parser : public LIEF::Parser {
|
||||
void build(void);
|
||||
void build_fat(void);
|
||||
|
||||
std::unique_ptr<BinaryStream> stream_;
|
||||
std::unique_ptr<VectorStream> stream_;
|
||||
std::vector<Binary*> binaries_;
|
||||
ParserConfig config_;
|
||||
};
|
||||
|
||||
@@ -81,10 +81,6 @@ class LIEF_API SegmentCommand : public LoadCommand {
|
||||
|
||||
const content_t& content(void) const;
|
||||
|
||||
inline int8_t index() const {
|
||||
return this->index_;
|
||||
}
|
||||
|
||||
void name(const std::string& name);
|
||||
void virtual_address(uint64_t virtualAddress);
|
||||
void virtual_size(uint64_t virtualSize);
|
||||
@@ -126,7 +122,6 @@ class LIEF_API SegmentCommand : public LoadCommand {
|
||||
uint32_t initProtection_{0};
|
||||
uint32_t nbSections_{0};
|
||||
uint32_t flags_{0};
|
||||
int8_t index_ = -1;
|
||||
content_t data_;
|
||||
sections_t sections_;
|
||||
relocations_t relocations_;
|
||||
|
||||
@@ -201,8 +201,7 @@ enum _LIEF_EN(DataRegionType) {
|
||||
enum _LIEF_EN(REBASE_TYPES) {
|
||||
_LIEF_EI(REBASE_TYPE_POINTER) = 1u,
|
||||
_LIEF_EI(REBASE_TYPE_TEXT_ABSOLUTE32) = 2u,
|
||||
_LIEF_EI(REBASE_TYPE_TEXT_PCREL32) = 3u,
|
||||
_LIEF_EI(REBASE_TYPE_THREADED) = 102u,
|
||||
_LIEF_EI(REBASE_TYPE_TEXT_PCREL32) = 3u
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -232,7 +231,6 @@ enum _LIEF_EN(BINDING_CLASS) {
|
||||
_LIEF_EI(BIND_CLASS_WEAK) = 1u,
|
||||
_LIEF_EI(BIND_CLASS_LAZY) = 2u,
|
||||
_LIEF_EI(BIND_CLASS_STANDARD) = 3u,
|
||||
_LIEF_EI(BIND_CLASS_THREADED) = 100u
|
||||
};
|
||||
|
||||
|
||||
@@ -271,15 +269,6 @@ enum _LIEF_EN_2(BIND_OPCODES, uint8_t) {
|
||||
_LIEF_EI(BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB) = 0xA0u, ///< Perform binding, also add following ULEB128 as address
|
||||
_LIEF_EI(BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED) = 0xB0u, ///< Perform binding, also add immediate (lower 4-bits) using scaling
|
||||
_LIEF_EI(BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB) = 0xC0u, ///< Perform binding for several symbols (as following ULEB128), and skip several bytes.
|
||||
_LIEF_EI(BIND_OPCODE_THREADED) = 0xD0u,
|
||||
|
||||
_LIEF_EI(BIND_OPCODE_THREADED_APPLY) = 0xD0u | 0x01u,
|
||||
_LIEF_EI(BIND_OPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB) = 0xD0u | 0x00u,
|
||||
};
|
||||
|
||||
enum _LIEF_EN_2(BIND_SUBOPCODE_THREADED, uint8_t) {
|
||||
_LIEF_EI(BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB) = 0x00u,
|
||||
_LIEF_EI(BIND_SUBOPCODE_THREADED_APPLY) = 0x01u,
|
||||
};
|
||||
|
||||
enum _LIEF_EN(EXPORT_SYMBOL_FLAGS) {
|
||||
|
||||
@@ -60,16 +60,16 @@ using it_imported_symbols = filter_iterator<symbols_t>;
|
||||
using it_const_imported_symbols = const_filter_iterator<symbols_t>;
|
||||
|
||||
using libraries_t = std::vector<DylibCommand*>;
|
||||
using it_libraries = ref_iterator<libraries_t&>;
|
||||
using it_const_libraries = const_ref_iterator<const libraries_t&>;
|
||||
using it_libraries = ref_iterator<libraries_t>;
|
||||
using it_const_libraries = const_ref_iterator<libraries_t>;
|
||||
|
||||
using segments_t = std::vector<SegmentCommand*>;
|
||||
using it_segments = ref_iterator<segments_t&>;
|
||||
using it_const_segments = const_ref_iterator<const segments_t&>;
|
||||
using it_segments = ref_iterator<segments_t>;
|
||||
using it_const_segments = const_ref_iterator<segments_t>;
|
||||
|
||||
using sections_t = std::vector<Section*>;
|
||||
using it_sections = ref_iterator<sections_t&>;
|
||||
using it_const_sections = const_ref_iterator<const sections_t&>;
|
||||
using it_sections = ref_iterator<sections_t>;
|
||||
using it_const_sections = const_ref_iterator<sections_t>;
|
||||
|
||||
using relocations_t = std::set<Relocation*, KeyCmp<Relocation>>; ///< Container used to store relocations
|
||||
using it_relocations = ref_iterator<relocations_t&>; ///< Iterator's type for relocations
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
#include "LIEF/OAT/Binary.hpp"
|
||||
|
||||
struct Profiler;
|
||||
|
||||
namespace LIEF {
|
||||
namespace VDEX {
|
||||
@@ -40,7 +39,6 @@ namespace OAT {
|
||||
//! @brief Class which parse an OAT file and transform into a OAT::Binary
|
||||
class LIEF_API Parser : public LIEF::Parser {
|
||||
public:
|
||||
friend struct ::Profiler;
|
||||
//! Parse an OAT file
|
||||
static std::unique_ptr<Binary> parse(const std::string& oat_file);
|
||||
static std::unique_ptr<Binary> parse(const std::string& oat_file, const std::string& vdex_file);
|
||||
|
||||
@@ -61,15 +61,6 @@ class LIEF_API Binary : public LIEF::Binary {
|
||||
//! Convert Virtual address to offset
|
||||
uint64_t va_to_offset(uint64_t VA);
|
||||
|
||||
//! Convert the given offset into a virtual address.
|
||||
//!
|
||||
//! @param[in] offset The offset to convert.
|
||||
//! @param[in] slide If not 0, it will replace the default base address (if any)
|
||||
uint64_t offset_to_virtual_address(uint64_t offset, uint64_t slide = 0) const override;
|
||||
|
||||
//! Return binary's imagebase. ``0`` if not relevant
|
||||
uint64_t imagebase(void) const override;
|
||||
|
||||
//! Find the section associated with the `offset`
|
||||
Section& section_from_offset(uint64_t offset);
|
||||
const Section& section_from_offset(uint64_t offset) const;
|
||||
|
||||
@@ -32,16 +32,14 @@
|
||||
|
||||
#include "LIEF/PE/Binary.hpp"
|
||||
|
||||
struct Profiler;
|
||||
|
||||
namespace LIEF {
|
||||
namespace PE {
|
||||
|
||||
//! @brief Class which reconstruct a PE binary from a PE::Binary object
|
||||
class LIEF_API Builder {
|
||||
class LIEF_API Builder
|
||||
{
|
||||
public:
|
||||
friend struct ::Profiler;
|
||||
|
||||
Builder(void) = delete;
|
||||
Builder(Binary* pe_binary);
|
||||
~Builder(void);
|
||||
|
||||
@@ -26,10 +26,8 @@
|
||||
#include "LIEF/Abstract/Parser.hpp"
|
||||
#include "LIEF/PE/enums.hpp"
|
||||
|
||||
struct Profiler;
|
||||
|
||||
namespace LIEF {
|
||||
class BinaryStream;
|
||||
class VectorStream;
|
||||
|
||||
namespace PE {
|
||||
class Debug;
|
||||
@@ -38,9 +36,8 @@ class Binary;
|
||||
struct pe_resource_directory_table;
|
||||
|
||||
class LIEF_API Parser : public LIEF::Parser {
|
||||
public:
|
||||
friend struct ::Profiler;
|
||||
|
||||
public:
|
||||
//! @brief Maximum size of the data read
|
||||
static constexpr size_t MAX_DATA_SIZE = 3_GB;
|
||||
|
||||
@@ -111,7 +108,7 @@ class LIEF_API Parser : public LIEF::Parser {
|
||||
uint32_t base_offset, uint32_t current_offset, uint32_t depth = 0);
|
||||
|
||||
|
||||
std::unique_ptr<BinaryStream> stream_;
|
||||
std::unique_ptr<VectorStream> stream_;
|
||||
Binary* binary_{nullptr};
|
||||
PE_TYPE type_;
|
||||
std::set<uint32_t> resource_visited_;
|
||||
|
||||
@@ -20,12 +20,9 @@
|
||||
|
||||
#include "LIEF/PE/enums.hpp"
|
||||
#include "LIEF/visibility.h"
|
||||
#include "LIEF/errors.hpp"
|
||||
|
||||
|
||||
namespace LIEF {
|
||||
class BinaryStream;
|
||||
|
||||
namespace PE {
|
||||
class Binary;
|
||||
class Import;
|
||||
@@ -50,9 +47,6 @@ LIEF_API PE_TYPE get_type(const std::string& file);
|
||||
//! Return `PE32` or `PE32+`
|
||||
LIEF_API PE_TYPE get_type(const std::vector<uint8_t>& raw);
|
||||
|
||||
// In this case we assume that stream contains a valid PE stream
|
||||
LIEF_LOCAL result<PE_TYPE> get_type_from_stream(BinaryStream& stream);
|
||||
|
||||
//! Compute the hash of imported functions
|
||||
//!
|
||||
//! By default, it generates an hash with the following properties:
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
#include "LIEF/VDEX/File.hpp"
|
||||
|
||||
struct Profiler;
|
||||
|
||||
namespace LIEF {
|
||||
namespace VDEX {
|
||||
@@ -33,8 +32,6 @@ namespace VDEX {
|
||||
//! @brief Class which parse an VDEX file and transform into a VDEX::File object
|
||||
class LIEF_API Parser {
|
||||
public:
|
||||
friend struct ::Profiler;
|
||||
|
||||
static std::unique_ptr<File> parse(const std::string& file);
|
||||
static std::unique_ptr<File> parse(const std::vector<uint8_t>& data, const std::string& name = "");
|
||||
|
||||
|
||||
@@ -187,7 +187,6 @@ LIEF_OAT_FORWARD(Class)
|
||||
// DEX
|
||||
// ===============================
|
||||
LIEF_DEX_FORWARD(File)
|
||||
LIEF_DEX_FORWARD(Field)
|
||||
LIEF_DEX_FORWARD(Method)
|
||||
LIEF_DEX_FORWARD(Header)
|
||||
LIEF_DEX_FORWARD(Class)
|
||||
@@ -573,9 +572,6 @@ class LIEF_API Visitor {
|
||||
//! Method to visit a LIEF::DEX::File
|
||||
LIEF_DEX_VISITABLE(File)
|
||||
|
||||
//! Method to visit a LIEF::DEX::Field
|
||||
LIEF_DEX_VISITABLE(Field)
|
||||
|
||||
//! Method to visit a LIEF::DEX::Method
|
||||
LIEF_DEX_VISITABLE(Method)
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ struct dict_iterator_pair {
|
||||
return const_cast<add_const_t<key_ref_t>>(this->key_);
|
||||
}
|
||||
|
||||
typename std::enable_if<!std::is_const<key_ref_t>::value, remove_const_t<key_ref_t>>::type
|
||||
typename std::enable_if<not std::is_const<key_ref_t>::value, remove_const_t<key_ref_t>>::type
|
||||
key(void) const {
|
||||
return const_cast<remove_const_t<key_ref_t>>(static_cast<const dict_iterator_pair*>(this)->key());
|
||||
}
|
||||
@@ -74,7 +74,7 @@ struct dict_iterator_pair {
|
||||
return const_cast<add_const_t<value_ref_t>>(*this->value_);
|
||||
}
|
||||
|
||||
typename std::enable_if<!std::is_const<value_ref_t>::value, remove_const_t<value_ref_t>>::type
|
||||
typename std::enable_if<not std::is_const<value_ref_t>::value, remove_const_t<value_ref_t>>::type
|
||||
value(void) const {
|
||||
return const_cast<remove_const_t<value_ref_t>>(static_cast<const dict_iterator_pair*>(this)->value());
|
||||
}
|
||||
@@ -185,7 +185,7 @@ class dict_iterator : public std::iterator<
|
||||
}
|
||||
|
||||
|
||||
//typename std::enable_if<!std::is_const<ref_t>::value, remove_const_t<ref_t>>::type
|
||||
//typename std::enable_if<not std::is_const<ref_t>::value, remove_const_t<ref_t>>::type
|
||||
//operator[](size_t n) {
|
||||
// return const_cast<remove_const_t<ref_t>>(static_cast<const dict_iterator*>(this)->operator[](n));
|
||||
//}
|
||||
@@ -225,12 +225,12 @@ class dict_iterator : public std::iterator<
|
||||
|
||||
|
||||
bool operator>=(const dict_iterator& rhs) const {
|
||||
return !(*this < rhs);
|
||||
return not (*this < rhs);
|
||||
}
|
||||
|
||||
|
||||
bool operator<=(const dict_iterator& rhs) const {
|
||||
return !(*this > rhs);
|
||||
return not (*this > rhs);
|
||||
}
|
||||
|
||||
dict_iterator begin(void) const {
|
||||
@@ -257,7 +257,7 @@ class dict_iterator : public std::iterator<
|
||||
}
|
||||
|
||||
bool operator!=(const dict_iterator& other) const {
|
||||
return !(*this == other);
|
||||
return not (*this == other);
|
||||
}
|
||||
|
||||
size_t size(void) const {
|
||||
@@ -265,7 +265,7 @@ class dict_iterator : public std::iterator<
|
||||
}
|
||||
|
||||
|
||||
typename std::enable_if<!std::is_const<ref_t>::value, remove_const_t<ref_t>>::type
|
||||
typename std::enable_if<not std::is_const<ref_t>::value, remove_const_t<ref_t>>::type
|
||||
operator*() {
|
||||
return const_cast<remove_const_t<ref_t>>(static_cast<const dict_iterator*>(this)->operator*());
|
||||
}
|
||||
@@ -278,13 +278,13 @@ class dict_iterator : public std::iterator<
|
||||
}
|
||||
|
||||
template<typename U = typename DT::value_type>
|
||||
typename std::enable_if<!std::is_pointer<U>::value, add_const_t<ref_t>>::type
|
||||
typename std::enable_if<not std::is_pointer<U>::value, add_const_t<ref_t>>::type
|
||||
operator*() const {
|
||||
return const_cast<add_const_t<ref_t>>(*(this->it_));
|
||||
}
|
||||
|
||||
|
||||
typename std::enable_if<!std::is_const<pointer_t>::value, pointer_t>::type
|
||||
typename std::enable_if<not std::is_const<pointer_t>::value, pointer_t>::type
|
||||
operator->() {
|
||||
return const_cast<remove_const_t<pointer_t>>(static_cast<const ref_iterator*>(this)->operator->());
|
||||
}
|
||||
|
||||
+15
-15
@@ -124,7 +124,7 @@ class ref_iterator : public std::iterator<
|
||||
}
|
||||
|
||||
|
||||
typename std::enable_if<!std::is_const<ref_t>::value, remove_const_t<ref_t>>::type
|
||||
typename std::enable_if<not std::is_const<ref_t>::value, remove_const_t<ref_t>>::type
|
||||
operator[](size_t n) {
|
||||
return const_cast<remove_const_t<ref_t>>(static_cast<const ref_iterator*>(this)->operator[](n));
|
||||
}
|
||||
@@ -174,12 +174,12 @@ class ref_iterator : public std::iterator<
|
||||
|
||||
|
||||
bool operator>=(const ref_iterator& rhs) const {
|
||||
return !(*this < rhs);
|
||||
return not (*this < rhs);
|
||||
}
|
||||
|
||||
|
||||
bool operator<=(const ref_iterator& rhs) const {
|
||||
return !(*this > rhs);
|
||||
return not (*this > rhs);
|
||||
}
|
||||
|
||||
ref_iterator begin(void) const {
|
||||
@@ -206,7 +206,7 @@ class ref_iterator : public std::iterator<
|
||||
}
|
||||
|
||||
bool operator!=(const ref_iterator& other) const {
|
||||
return !(*this == other);
|
||||
return not (*this == other);
|
||||
}
|
||||
|
||||
size_t size(void) const {
|
||||
@@ -214,7 +214,7 @@ class ref_iterator : public std::iterator<
|
||||
}
|
||||
|
||||
|
||||
typename std::enable_if<!std::is_const<ref_t>::value, remove_const_t<ref_t>>::type
|
||||
typename std::enable_if<not std::is_const<ref_t>::value, remove_const_t<ref_t>>::type
|
||||
operator*() {
|
||||
return const_cast<remove_const_t<ref_t>>(static_cast<const ref_iterator*>(this)->operator*());
|
||||
}
|
||||
@@ -227,13 +227,13 @@ class ref_iterator : public std::iterator<
|
||||
}
|
||||
|
||||
template<typename U = typename DT::value_type>
|
||||
typename std::enable_if<!std::is_pointer<U>::value, add_const_t<ref_t>>::type
|
||||
typename std::enable_if<not std::is_pointer<U>::value, add_const_t<ref_t>>::type
|
||||
operator*() const {
|
||||
return const_cast<add_const_t<ref_t>>(*(this->it_));
|
||||
}
|
||||
|
||||
|
||||
typename std::enable_if<!std::is_const<pointer_t>::value, pointer_t>::type
|
||||
typename std::enable_if<not std::is_const<pointer_t>::value, pointer_t>::type
|
||||
operator->() {
|
||||
return const_cast<remove_const_t<pointer_t>>(static_cast<const ref_iterator*>(this)->operator->());
|
||||
}
|
||||
@@ -283,7 +283,7 @@ class filter_iterator : public std::iterator<
|
||||
this->it_ = std::begin(this->container_);
|
||||
|
||||
if (this->it_ != std::end(this->container_)) {
|
||||
if (!std::all_of(std::begin(this->filters_), std::end(this->filters_), [this] (const filter_t& f) {return f(*this->it_);})) {
|
||||
if (not std::all_of(std::begin(this->filters_), std::end(this->filters_), [this] (const filter_t& f) {return f(*this->it_);})) {
|
||||
this->next();
|
||||
}
|
||||
}
|
||||
@@ -299,7 +299,7 @@ class filter_iterator : public std::iterator<
|
||||
this->it_ = std::begin(this->container_);
|
||||
|
||||
if (this->it_ != std::end(this->container_)) {
|
||||
if (!std::all_of(std::begin(this->filters_), std::end(this->filters_), [this] (const filter_t& f) {return f(*this->it_);})) {
|
||||
if (not std::all_of(std::begin(this->filters_), std::end(this->filters_), [this] (const filter_t& f) {return f(*this->it_);})) {
|
||||
this->next();
|
||||
}
|
||||
}
|
||||
@@ -377,7 +377,7 @@ class filter_iterator : public std::iterator<
|
||||
return this->end();
|
||||
}
|
||||
|
||||
typename std::enable_if<!std::is_const<ref_t>::value, remove_const_t<ref_t>>::type
|
||||
typename std::enable_if<not std::is_const<ref_t>::value, remove_const_t<ref_t>>::type
|
||||
operator*() {
|
||||
return const_cast<remove_const_t<ref_t>>(static_cast<const filter_iterator*>(this)->operator*());
|
||||
}
|
||||
@@ -390,13 +390,13 @@ class filter_iterator : public std::iterator<
|
||||
}
|
||||
|
||||
template<typename U = typename DT::value_type>
|
||||
typename std::enable_if<!std::is_pointer<U>::value, add_const_t<ref_t>>::type
|
||||
typename std::enable_if<not std::is_pointer<U>::value, add_const_t<ref_t>>::type
|
||||
operator*() const {
|
||||
return const_cast<add_const_t<ref_t>>(*(this->it_));
|
||||
}
|
||||
|
||||
|
||||
typename std::enable_if<!std::is_const<ref_t>::value, remove_const_t<ref_t>>::type
|
||||
typename std::enable_if<not std::is_const<ref_t>::value, remove_const_t<ref_t>>::type
|
||||
operator[](size_t n) {
|
||||
return const_cast<remove_const_t<ref_t>>(static_cast<const filter_iterator*>(this)->operator[](n));
|
||||
}
|
||||
@@ -410,7 +410,7 @@ class filter_iterator : public std::iterator<
|
||||
}
|
||||
|
||||
|
||||
typename std::enable_if<!std::is_const<pointer_t>::value, pointer_t>::type
|
||||
typename std::enable_if<not std::is_const<pointer_t>::value, pointer_t>::type
|
||||
operator->() {
|
||||
return const_cast<remove_const_t<pointer_t>>(static_cast<const filter_iterator*>(this)->operator->());
|
||||
}
|
||||
@@ -442,7 +442,7 @@ class filter_iterator : public std::iterator<
|
||||
}
|
||||
|
||||
bool operator!=(const filter_iterator& other) const {
|
||||
return !(*this == other);
|
||||
return not (*this == other);
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -457,7 +457,7 @@ class filter_iterator : public std::iterator<
|
||||
this->distance_++;
|
||||
} while(
|
||||
this->it_ != std::end(this->container_) and
|
||||
!std::all_of(
|
||||
not std::all_of(
|
||||
std::begin(this->filters_),
|
||||
std::end(this->filters_),
|
||||
[this] (const filter_t& f) {
|
||||
|
||||
@@ -16,42 +16,4 @@
|
||||
#ifndef LIEF_PLATFORMS_H_
|
||||
#define LIEF_PLATFORMS_H_
|
||||
#include "LIEF/platforms/android.hpp"
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include "TargetConditionals.h"
|
||||
#endif
|
||||
|
||||
namespace LIEF {
|
||||
|
||||
enum class PLATFORMS {
|
||||
UNKNOWN = 0,
|
||||
LINUX,
|
||||
ANDROID_PLAT,
|
||||
WINDOWS,
|
||||
IOS,
|
||||
OSX,
|
||||
};
|
||||
|
||||
constexpr PLATFORMS current_platform() {
|
||||
#if defined(__ANDROID__)
|
||||
return PLATFORMS::ANDROID_PLAT;
|
||||
#elif defined(__linux__)
|
||||
return PLATFORMS::LINUX;
|
||||
#elif defined(_WIN64) || defined(_WIN32)
|
||||
return PLATFORMS::WINDOWS;
|
||||
#elif defined(__APPLE__)
|
||||
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
|
||||
return PLATFORMS::IOS;
|
||||
#else
|
||||
return PLATFORMS::OSX;
|
||||
#endif
|
||||
#else
|
||||
return PLATFORMS::UNKNOWN;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/usr/bin/sh
|
||||
set -ex
|
||||
|
||||
mkdir -p build/osx-aarch64/static-release && mkdir -p build/osx-aarch64/shared-release
|
||||
pushd build/osx-aarch64/shared-release
|
||||
|
||||
cmake ../../.. -GNinja \
|
||||
-DBUILD_SHARED_LIBS=on \
|
||||
-DLIEF_PYTHON_API=off \
|
||||
-DLIEF_INSTALL_COMPILED_EXAMPLES=off \
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
ninja
|
||||
|
||||
|
||||
popd
|
||||
pushd build/osx-aarch64/static-release
|
||||
|
||||
cmake ../../.. -GNinja \
|
||||
-DBUILD_SHARED_LIBS=off \
|
||||
-DLIEF_PYTHON_API=off \
|
||||
-DLIEF_INSTALL_COMPILED_EXAMPLES=on \
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
ninja
|
||||
|
||||
popd
|
||||
pushd build/osx-aarch64
|
||||
cpack --config ../../cmake/cpack.config.cmake
|
||||
popd
|
||||
|
||||
/bin/mv build/osx-aarch64/*.tar.gz build/
|
||||
@@ -45,10 +45,6 @@ class LiefDistribution(setuptools.Distribution):
|
||||
('lief-no-vdex', None, 'Disable VDEX module'),
|
||||
('lief-no-oat', None, 'Disable OAT module'),
|
||||
('lief-no-dex', None, 'Disable DEX module'),
|
||||
|
||||
('lief-no-cache', None, 'Do not use compiler cache (ccache)'),
|
||||
|
||||
('spdlog-dir=', None, 'Path to the directory that contains spdlogConfig.cmake'),
|
||||
]
|
||||
|
||||
def __init__(self, attrs=None):
|
||||
@@ -70,10 +66,6 @@ class LiefDistribution(setuptools.Distribution):
|
||||
|
||||
self.lief_no_android = False
|
||||
self.doc = False
|
||||
|
||||
self.lief_no_cache = False
|
||||
|
||||
self.spdlog_dir = None
|
||||
super().__init__(attrs)
|
||||
|
||||
|
||||
@@ -116,7 +108,7 @@ class BuildLibrary(build_ext):
|
||||
filename = self.get_ext_filename(fullname)
|
||||
|
||||
jobs = self.parallel if self.parallel else 1
|
||||
cmake_args = ["-DLIEF_FORCE_API_EXPORTS=ON"]
|
||||
cmake_args = []
|
||||
|
||||
source_dir = ext.sourcedir
|
||||
build_temp = self.build_temp
|
||||
@@ -135,8 +127,7 @@ class BuildLibrary(build_ext):
|
||||
|
||||
cmake_args += [
|
||||
'-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={}'.format(cmake_library_output_directory),
|
||||
'-DPython3_ROOT_DIR={}'.format(sys.prefix),
|
||||
'-DPython3_FIND_STRATEGY=LOCATION',
|
||||
'-DPYTHON_EXECUTABLE={}'.format(sys.executable),
|
||||
'-DLIEF_PYTHON_API=on',
|
||||
]
|
||||
|
||||
@@ -163,15 +154,6 @@ class BuildLibrary(build_ext):
|
||||
else:
|
||||
cmake_args += ["-DLIEF_LOGGING_DEBUG=off"]
|
||||
|
||||
if self.distribution.lief_no_cache:
|
||||
cmake_args += ["-DLIEF_USE_CCACHE=off"]
|
||||
|
||||
# Setup spdlog configuration flags if
|
||||
# the user provides --spdlog-dir
|
||||
if self.distribution.spdlog_dir is not None:
|
||||
cmake_args.append("-DLIEF_EXTERNAL_SPDLOG=ON")
|
||||
cmake_args.append("-Dspdlog_DIR={}".format(self.distribution.spdlog_dir))
|
||||
|
||||
# Main formats
|
||||
# ============
|
||||
if self.distribution.lief_no_elf:
|
||||
@@ -261,6 +243,7 @@ class BuildLibrary(build_ext):
|
||||
|
||||
if platform.system() == "Windows":
|
||||
build_cmd = ['cmake', '--build', '.', '--target', "lief_samples"] + build_args
|
||||
#log.info(" ".join(build_cmd))
|
||||
|
||||
if self.distribution.lief_test:
|
||||
subprocess.check_call(['cmake', '--build', '.', '--target', "lief_samples"] + build_args, cwd=self.build_temp, env=env)
|
||||
@@ -443,7 +426,7 @@ def get_pkg_info_version(pkg_info_file):
|
||||
|
||||
|
||||
def get_version() -> str:
|
||||
version = "0.12.0"
|
||||
version = "0.11.3"
|
||||
pkg_info = os.path.join(CURRENT_DIR, "{}.egg-info".format(PACKAGE_NAME), "PKG-INFO")
|
||||
git_dir = os.path.join(CURRENT_DIR, ".git")
|
||||
if os.path.isdir(git_dir):
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "LIEF/utils.hpp"
|
||||
|
||||
#include "LIEF/ART/EnumToString.hpp"
|
||||
#include "LIEF/PE/utils.hpp"
|
||||
|
||||
namespace LIEF {
|
||||
namespace ART {
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
/* Copyright 2017 - 2021 R. Thomas
|
||||
* Copyright 2017 - 2021 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 <iterator>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include <mbedtls/platform.h>
|
||||
#include <mbedtls/asn1.h>
|
||||
#include <mbedtls/error.h>
|
||||
#include <mbedtls/oid.h>
|
||||
#include <mbedtls/x509_crt.h>
|
||||
|
||||
#include "logging.hpp"
|
||||
|
||||
#include "LIEF/Abstract/Binary.hpp"
|
||||
#include "LIEF/BinaryStream/MemoryStream.hpp"
|
||||
#include "LIEF/exception.hpp"
|
||||
namespace LIEF {
|
||||
|
||||
|
||||
MemoryStream::MemoryStream(uintptr_t base_address) :
|
||||
baseaddr_{base_address},
|
||||
size_{-1llu}
|
||||
{}
|
||||
|
||||
MemoryStream::MemoryStream(uintptr_t base_address, uint64_t size) :
|
||||
baseaddr_{base_address},
|
||||
size_{size}
|
||||
{}
|
||||
|
||||
uint64_t MemoryStream::size(void) const {
|
||||
return this->size_;
|
||||
}
|
||||
|
||||
const void* MemoryStream::read_at(uint64_t offset, uint64_t, bool) const {
|
||||
const uintptr_t va = this->baseaddr_ + offset;
|
||||
if (this->binary_ != nullptr) {
|
||||
return reinterpret_cast<const void*>(this->binary_->offset_to_virtual_address(offset, this->baseaddr_));
|
||||
}
|
||||
return reinterpret_cast<const void*>(va);
|
||||
}
|
||||
|
||||
|
||||
result<size_t> MemoryStream::asn1_read_tag(int tag) {
|
||||
// TODO(romain)
|
||||
return 0;
|
||||
}
|
||||
|
||||
result<size_t> MemoryStream::asn1_peek_len() {
|
||||
// TODO(romain)
|
||||
return 0;
|
||||
}
|
||||
|
||||
result<size_t> MemoryStream::asn1_read_len() {
|
||||
// TODO(romain)
|
||||
return 0;
|
||||
}
|
||||
|
||||
result<std::string> MemoryStream::asn1_read_alg() {
|
||||
// TODO(romain)
|
||||
return std::string();
|
||||
}
|
||||
|
||||
result<std::string> MemoryStream::asn1_read_oid() {
|
||||
// TODO(romain)
|
||||
return std::string();
|
||||
}
|
||||
|
||||
|
||||
result<int32_t> MemoryStream::asn1_read_int() {
|
||||
// TODO(romain)
|
||||
return 0;
|
||||
}
|
||||
|
||||
result<std::vector<uint8_t>> MemoryStream::asn1_read_bitstring() {
|
||||
// TODO(romain)
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
result<std::vector<uint8_t>> MemoryStream::asn1_read_octet_string() {
|
||||
// TODO(romain)
|
||||
return {};
|
||||
}
|
||||
|
||||
result<std::unique_ptr<mbedtls_x509_crt>> MemoryStream::asn1_read_cert() {
|
||||
// TODO(romain)
|
||||
return std::unique_ptr<mbedtls_x509_crt>{nullptr};
|
||||
}
|
||||
|
||||
result<std::string> MemoryStream::x509_read_names() {
|
||||
// TODO(romain)
|
||||
return std::string();
|
||||
}
|
||||
|
||||
result<std::vector<uint8_t>> MemoryStream::x509_read_serial() {
|
||||
// TODO(romain)
|
||||
return {};
|
||||
}
|
||||
|
||||
result<std::unique_ptr<mbedtls_x509_time>> MemoryStream::x509_read_time() {
|
||||
// TODO(romain)
|
||||
return std::unique_ptr<mbedtls_x509_time>{nullptr};
|
||||
}
|
||||
|
||||
MemoryStream::~MemoryStream() = default;
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ set(LIEF_DEX_SRC
|
||||
${CMAKE_CURRENT_LIST_DIR}/Header.tcc
|
||||
${CMAKE_CURRENT_LIST_DIR}/Class.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/Method.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/Field.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/instructions.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/CodeInfo.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/Type.cpp
|
||||
@@ -38,7 +37,6 @@ set(LIEF_DEX_INC_FILES
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/DEX/Header.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/DEX/Class.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/DEX/Method.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/DEX/Field.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/DEX/CodeInfo.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/DEX/Parser.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/DEX/type_traits.hpp"
|
||||
|
||||
@@ -157,14 +157,6 @@ it_methods Class::methods(void) {
|
||||
return this->methods_;
|
||||
}
|
||||
|
||||
it_const_fields Class::fields(void) const {
|
||||
return this->fields_;
|
||||
}
|
||||
|
||||
it_fields Class::fields(void) {
|
||||
return this->fields_;
|
||||
}
|
||||
|
||||
|
||||
it_methods Class::methods(const std::string& name) {
|
||||
return this->method_from_name(name);
|
||||
@@ -186,25 +178,6 @@ methods_t Class::method_from_name(const std::string& name) const {
|
||||
return mtd;
|
||||
}
|
||||
|
||||
it_fields Class::fields(const std::string& name) {
|
||||
return this->field_from_name(name);
|
||||
}
|
||||
|
||||
it_const_fields Class::fields(const std::string& name) const {
|
||||
return this->field_from_name(name);
|
||||
}
|
||||
|
||||
fields_t Class::field_from_name(const std::string& name) const {
|
||||
fields_t fld;
|
||||
std::copy_if(
|
||||
std::begin(this->fields_), std::end(this->fields_),
|
||||
std::back_inserter(fld),
|
||||
[&name] (const Field* f) {
|
||||
return f->name() == name;
|
||||
});
|
||||
return fld;
|
||||
}
|
||||
|
||||
size_t Class::index(void) const {
|
||||
return this->original_index_;
|
||||
}
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
#include "LIEF/DEX/Field.hpp"
|
||||
#include "LIEF/DEX/Class.hpp"
|
||||
#include "logging.hpp"
|
||||
#include "LIEF/DEX/hash.hpp"
|
||||
#include "LIEF/DEX/enums.hpp"
|
||||
#include "LIEF/DEX/EnumToString.hpp"
|
||||
|
||||
#include <numeric>
|
||||
|
||||
|
||||
namespace LIEF {
|
||||
namespace DEX {
|
||||
|
||||
Field::Field(const Field&) = default;
|
||||
Field& Field::operator=(const Field&) = default;
|
||||
|
||||
Field::Field(void) = default;
|
||||
|
||||
Field::Field(const std::string& name, Class* parent) :
|
||||
name_{name},
|
||||
parent_{parent},
|
||||
access_flags_{ACCESS_FLAGS::ACC_UNKNOWN},
|
||||
original_index_{-1u}
|
||||
{}
|
||||
|
||||
const std::string& Field::name(void) const {
|
||||
return this->name_;
|
||||
}
|
||||
|
||||
bool Field::has_class(void) const {
|
||||
return this->parent_ != nullptr;
|
||||
}
|
||||
|
||||
const Class& Field::cls(void) const {
|
||||
if (not this->has_class()) {
|
||||
throw not_found("Can't find class associated with " + this->name());
|
||||
}
|
||||
return *this->parent_;
|
||||
}
|
||||
|
||||
Class& Field::cls(void) {
|
||||
return const_cast<Class&>(static_cast<const Field*>(this)->cls());
|
||||
}
|
||||
|
||||
size_t Field::index(void) const {
|
||||
return this->original_index_;
|
||||
}
|
||||
|
||||
bool Field::is_static(void) const {
|
||||
return this->is_static_;
|
||||
}
|
||||
|
||||
void Field::set_static(bool v) {
|
||||
this->is_static_ = v;
|
||||
}
|
||||
|
||||
|
||||
bool Field::has(ACCESS_FLAGS f) const {
|
||||
return (this->access_flags_ & f);
|
||||
}
|
||||
|
||||
Field::access_flags_list_t Field::access_flags(void) const {
|
||||
Field::access_flags_list_t flags;
|
||||
|
||||
std::copy_if(
|
||||
std::begin(access_flags_list), std::end(access_flags_list),
|
||||
std::back_inserter(flags),
|
||||
std::bind(static_cast<bool (Field::*)(ACCESS_FLAGS) const>(&Field::has), this, std::placeholders::_1));
|
||||
|
||||
return flags;
|
||||
|
||||
}
|
||||
|
||||
const Type& Field::type(void) const {
|
||||
CHECK(this->type_ != nullptr, "Type is null!");
|
||||
return *this->type_;
|
||||
}
|
||||
|
||||
Type& Field::type(void) {
|
||||
return const_cast<Type&>(static_cast<const Field*>(this)->type());
|
||||
}
|
||||
|
||||
void Field::accept(Visitor& visitor) const {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
bool Field::operator==(const Field& rhs) const {
|
||||
size_t hash_lhs = Hash::hash(*this);
|
||||
size_t hash_rhs = Hash::hash(rhs);
|
||||
return hash_lhs == hash_rhs;
|
||||
}
|
||||
|
||||
bool Field::operator!=(const Field& rhs) const {
|
||||
return not (*this == rhs);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const Field& field) {
|
||||
std::string pretty_cls_name = field.cls().fullname();
|
||||
if (not pretty_cls_name.empty()) {
|
||||
pretty_cls_name = pretty_cls_name.substr(1, pretty_cls_name.size() - 2);
|
||||
std::replace(std::begin(pretty_cls_name), std::end(pretty_cls_name), '/', '.');
|
||||
}
|
||||
|
||||
Method::access_flags_list_t aflags = field.access_flags();
|
||||
std::string flags_str = std::accumulate(
|
||||
std::begin(aflags),
|
||||
std::end(aflags),
|
||||
std::string{},
|
||||
[] (const std::string& l, ACCESS_FLAGS r) {
|
||||
std::string str = to_string(r);
|
||||
std::transform(std::begin(str), std::end(str), std::begin(str), ::tolower);
|
||||
return l.empty() ? str : l + " " + str;
|
||||
});
|
||||
|
||||
if (not flags_str.empty()) {
|
||||
os << flags_str << " ";
|
||||
}
|
||||
os << field.type()
|
||||
<< " "
|
||||
<< pretty_cls_name << "->" << field.name();
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
Field::~Field(void) = default;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -486,14 +486,6 @@ it_methods File::methods(void) {
|
||||
return this->methods_;
|
||||
}
|
||||
|
||||
it_const_fields File::fields(void) const {
|
||||
return this->fields_;
|
||||
}
|
||||
|
||||
it_fields File::fields(void) {
|
||||
return this->fields_;
|
||||
}
|
||||
|
||||
|
||||
it_const_strings File::strings(void) const {
|
||||
return this->strings_;
|
||||
|
||||
@@ -133,28 +133,6 @@ void Parser::resolve_external_methods(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void Parser::resolve_external_fields(void) {
|
||||
LIEF_DEBUG("Resolving external fields for #{:d} fields", this->class_field_map_.size());
|
||||
|
||||
for (const std::pair<const std::string, Field*>& p : this->class_field_map_) {
|
||||
const std::string& clazz = p.first;
|
||||
Field* field = p.second;
|
||||
|
||||
const auto it_inner_class = this->file_->classes_.find(clazz);
|
||||
if (it_inner_class == std::end(this->file_->classes_)) {
|
||||
Class* cls = new Class{clazz};
|
||||
cls->fields_.push_back(field);
|
||||
field->parent_ = cls;
|
||||
this->file_->classes_.emplace(clazz, cls);
|
||||
} else {
|
||||
Class* cls = it_inner_class->second;
|
||||
field->parent_ = cls;
|
||||
cls->fields_.push_back(field);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Parser::resolve_types(void) {
|
||||
for (auto&& p : this->class_type_map_) {
|
||||
if(this->file_->has_class(p.first)) {
|
||||
|
||||
+6
-99
@@ -41,7 +41,6 @@ void Parser::parse_file(void) {
|
||||
this->resolve_types();
|
||||
this->resolve_inheritance();
|
||||
this->resolve_external_methods();
|
||||
this->resolve_external_fields();
|
||||
|
||||
}
|
||||
|
||||
@@ -153,62 +152,10 @@ void Parser::parse_types(void) {
|
||||
|
||||
template<typename DEX_T>
|
||||
void Parser::parse_fields(void) {
|
||||
|
||||
Header::location_t fields_location = this->file_->header().fields();
|
||||
Header::location_t types_location = this->file_->header().types();
|
||||
|
||||
const uint64_t fields_offset = fields_location.first;
|
||||
|
||||
LIEF_DEBUG("Parsing #{:d} FIELDS at 0x{:x}", fields_location.second, fields_location.first);
|
||||
|
||||
for (size_t i = 0; i < fields_location.second; ++i) {
|
||||
const field_id_item& item = this->stream_->peek<field_id_item>(fields_offset + i * sizeof(field_id_item));
|
||||
|
||||
// Class name in which the field is defined
|
||||
if (item.class_idx > types_location.second) {
|
||||
LIEF_WARN("Type index for field name is corrupted");
|
||||
continue;
|
||||
}
|
||||
uint32_t class_name_idx = this->stream_->peek<uint32_t>(types_location.first + item.class_idx * sizeof(uint32_t));
|
||||
|
||||
if (class_name_idx > this->file_->strings_.size()) {
|
||||
LIEF_WARN("String index for class name is corrupted");
|
||||
continue;
|
||||
}
|
||||
std::string clazz = *this->file_->strings_[class_name_idx];
|
||||
if (not clazz.empty() and clazz[0] == '[') {
|
||||
size_t pos = clazz.find_last_of('[');
|
||||
clazz = clazz.substr(pos + 1);
|
||||
}
|
||||
|
||||
// Type
|
||||
// =======================
|
||||
if (item.type_idx >= this->file_->types_.size()) {
|
||||
LIEF_WARN("Type #{:d} out of bound ({:d})", item.type_idx, this->file_->types_.size());
|
||||
break;
|
||||
}
|
||||
Type* type = this->file_->types_[item.type_idx];
|
||||
|
||||
// Field Name
|
||||
if (item.name_idx > this->file_->strings_.size()) {
|
||||
LIEF_WARN("Name of field #{:d} is out of bound!", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string name = *this->file_->strings_[item.name_idx];
|
||||
if (name.empty()) {
|
||||
LIEF_WARN("Empty field name");
|
||||
}
|
||||
|
||||
Field* field = new Field{name};
|
||||
field->original_index_ = i;
|
||||
field->type_ = type;
|
||||
this->file_->fields_.push_back(field);
|
||||
|
||||
|
||||
if (not clazz.empty() and clazz[0] != '[') {
|
||||
this->class_field_map_.emplace(clazz, field);
|
||||
}
|
||||
}
|
||||
// TODO(romain): To implement
|
||||
}
|
||||
|
||||
template<typename DEX_T>
|
||||
@@ -442,26 +389,14 @@ void Parser::parse_class_data(uint32_t offset, Class* cls) {
|
||||
// =============
|
||||
for (size_t field_idx = 0, i = 0; i < static_fields_size; ++i) {
|
||||
field_idx += this->stream_->read_uleb128();
|
||||
if (field_idx > file_->fields_.size()) {
|
||||
LIEF_WARN("Corrupted field index #{:d} for class: {} ({:d} fields)",
|
||||
field_idx, cls->fullname(), this->file_->fields_.size());
|
||||
break;
|
||||
}
|
||||
|
||||
this->parse_field<DEX_T>(field_idx, cls, true);
|
||||
/* uint64_t access_flags = */ this->stream_->read_uleb128();
|
||||
}
|
||||
|
||||
// Instance Fields
|
||||
// ===============
|
||||
// Instances
|
||||
// =========
|
||||
for (size_t field_idx = 0, i = 0; i < instance_fields_size; ++i) {
|
||||
field_idx += this->stream_->read_uleb128();
|
||||
if (field_idx > file_->fields_.size()) {
|
||||
LIEF_WARN("Corrupted field index #{:d} for class: {} ({:d} fields)",
|
||||
field_idx, cls->fullname(), this->file_->fields_.size());
|
||||
break;
|
||||
}
|
||||
|
||||
this->parse_field<DEX_T>(field_idx, cls, false);
|
||||
/* uint64_t access_flags = */ this->stream_->read_uleb128();
|
||||
}
|
||||
|
||||
// Direct Methods
|
||||
@@ -493,34 +428,6 @@ void Parser::parse_class_data(uint32_t offset, Class* cls) {
|
||||
}
|
||||
|
||||
|
||||
template<typename DEX_T>
|
||||
void Parser::parse_field(size_t index, Class* cls, bool is_static) {
|
||||
// Access Flags
|
||||
uint64_t access_flags = this->stream_->read_uleb128();
|
||||
|
||||
Field* field = this->file_->fields_[index];
|
||||
field->set_static(is_static);
|
||||
|
||||
if (field->index() != index) {
|
||||
LIEF_WARN("field->index() is not consistent");
|
||||
return;
|
||||
}
|
||||
|
||||
field->access_flags_ = static_cast<uint32_t>(access_flags);
|
||||
field->parent_ = cls;
|
||||
cls->fields_.push_back(field);
|
||||
|
||||
auto&& range = this->class_field_map_.equal_range(cls->fullname());
|
||||
for (auto it = range.first; it != range.second;) {
|
||||
if (it->second == field) {
|
||||
it = this->class_field_map_.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename DEX_T>
|
||||
void Parser::parse_method(size_t index, Class* cls, bool is_virtual) {
|
||||
// Access Flags
|
||||
|
||||
@@ -59,21 +59,14 @@ void Hash::visit(const CodeInfo& /*code_info*/) {
|
||||
|
||||
void Hash::visit(const Class& cls) {
|
||||
|
||||
it_const_fields fields = cls.fields();
|
||||
it_const_methods methods = cls.methods();
|
||||
this->process(cls.fullname());
|
||||
this->process(cls.source_filename());
|
||||
this->process(cls.access_flags());
|
||||
|
||||
this->process(std::begin(fields), std::end(fields));
|
||||
this->process(std::begin(methods), std::end(methods));
|
||||
}
|
||||
|
||||
void Hash::visit(const Field& field) {
|
||||
this->process(field.name());
|
||||
this->process(field.type());
|
||||
}
|
||||
|
||||
void Hash::visit(const Method& method) {
|
||||
this->process(method.name());
|
||||
this->process(method.bytecode());
|
||||
|
||||
@@ -85,13 +85,6 @@ void JsonVisitor::visit(const Class& cls) {
|
||||
flags.emplace_back(to_string(f));
|
||||
}
|
||||
|
||||
std::vector<json> fields;
|
||||
for (const Field& f : cls.fields()) {
|
||||
JsonVisitor fv;
|
||||
fv(f);
|
||||
fields.emplace_back(fv.get());
|
||||
}
|
||||
|
||||
std::vector<json> methods;
|
||||
for (const Method& m : cls.methods()) {
|
||||
JsonVisitor mv;
|
||||
@@ -102,7 +95,6 @@ void JsonVisitor::visit(const Class& cls) {
|
||||
this->node_["source_filename"] = cls.source_filename();
|
||||
this->node_["access_flags"] = flags;
|
||||
this->node_["index"] = cls.index();
|
||||
this->node_["fields"] = fields;
|
||||
this->node_["methods"] = methods;
|
||||
|
||||
if (cls.has_parent()) {
|
||||
@@ -110,22 +102,6 @@ void JsonVisitor::visit(const Class& cls) {
|
||||
}
|
||||
}
|
||||
|
||||
void JsonVisitor::visit(const Field& field) {
|
||||
std::vector<json> flags;
|
||||
for (ACCESS_FLAGS f : field.access_flags()) {
|
||||
flags.emplace_back(to_string(f));
|
||||
}
|
||||
|
||||
JsonVisitor type_visitor;
|
||||
type_visitor(field.type());
|
||||
|
||||
this->node_["name"] = field.name();
|
||||
this->node_["index"] = field.index();
|
||||
this->node_["is_static"] = field.is_static();
|
||||
this->node_["type"] = type_visitor.get();
|
||||
this->node_["access_flags"] = flags;
|
||||
}
|
||||
|
||||
void JsonVisitor::visit(const Method& method) {
|
||||
std::vector<json> flags;
|
||||
for (ACCESS_FLAGS f : method.access_flags()) {
|
||||
|
||||
+8
-38
@@ -1584,9 +1584,8 @@ bool Binary::has_section_with_va(uint64_t va) const {
|
||||
if (section == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return (section->virtual_address() != 0 and
|
||||
(section->virtual_address() <= va) and
|
||||
(section->virtual_address() + section->size()) > va);
|
||||
return ((section->virtual_address() <= va) and
|
||||
(section->virtual_address() + section->size()) > va);
|
||||
});
|
||||
return it_section != this->sections_.cend();
|
||||
}
|
||||
@@ -1630,8 +1629,9 @@ Symbol& Binary::add_dynamic_symbol(const Symbol& symbol, const SymbolVersion* ve
|
||||
}
|
||||
|
||||
uint64_t Binary::virtual_address_to_offset(uint64_t virtual_address) const {
|
||||
const auto it_segment = std::find_if(
|
||||
std::begin(this->segments_), std::end(this->segments_),
|
||||
auto&& it_segment = std::find_if(
|
||||
std::begin(this->segments_),
|
||||
std::end(this->segments_),
|
||||
[virtual_address] (const Segment* segment)
|
||||
{
|
||||
if (segment == nullptr) {
|
||||
@@ -1655,36 +1655,6 @@ uint64_t Binary::virtual_address_to_offset(uint64_t virtual_address) const {
|
||||
|
||||
}
|
||||
|
||||
uint64_t Binary::offset_to_virtual_address(uint64_t offset, uint64_t slide) const {
|
||||
const auto it_segment = std::find_if(
|
||||
std::begin(this->segments_), std::end(this->segments_),
|
||||
[offset] (const Segment* segment) {
|
||||
if (segment == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
segment->type() == SEGMENT_TYPES::PT_LOAD and
|
||||
segment->file_offset() <= offset and
|
||||
segment->file_offset() + segment->physical_size() > offset
|
||||
);
|
||||
});
|
||||
|
||||
if (it_segment == std::end(this->segments_)) {
|
||||
if (slide > 0) {
|
||||
return slide + offset;
|
||||
}
|
||||
return this->imagebase() + offset;
|
||||
}
|
||||
|
||||
const uint64_t base_address = (*it_segment)->virtual_address() - (*it_segment)->file_offset();
|
||||
if (slide > 0) {
|
||||
return (base_address - this->imagebase()) + slide + offset;
|
||||
}
|
||||
|
||||
return base_address + offset;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool Binary::has_interpreter(void) const {
|
||||
auto&& it_segment_interp = std::find_if(
|
||||
@@ -1746,6 +1716,7 @@ Section& Binary::section_from_offset(uint64_t offset) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
const Section& Binary::section_from_virtual_address(uint64_t address) const {
|
||||
auto&& it_section = std::find_if(
|
||||
this->sections_.cbegin(),
|
||||
@@ -1754,9 +1725,8 @@ const Section& Binary::section_from_virtual_address(uint64_t address) const {
|
||||
if (section == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return ((section->virtual_address() != 0) and
|
||||
(section->virtual_address() <= address) and
|
||||
(section->virtual_address() + section->size()) > address);
|
||||
return ((section->virtual_address() <= address) and
|
||||
(section->virtual_address() + section->size()) > address);
|
||||
});
|
||||
|
||||
if (it_section == this->sections_.cend()) {
|
||||
|
||||
+1
-1
@@ -242,7 +242,7 @@ void Binary::patch_addend(Relocation& relocation, uint64_t from, uint64_t shift)
|
||||
return;
|
||||
}
|
||||
|
||||
if (relative_offset >= segment_size or (relative_offset + sizeof(T)) > segment_size) {
|
||||
if (relative_offset >= segment_size or (relative_offset + sizeof(T)) >= segment_size) {
|
||||
LIEF_DEBUG("Offset out of bound for relocation: {}", relocation);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -111,45 +111,6 @@ void Builder::write(const std::string& filename) const {
|
||||
}
|
||||
|
||||
|
||||
uint32_t Builder::sort_dynamic_symbols(void) {
|
||||
static const std::string dynsym_section_name = ".dynsym";
|
||||
const auto it_begin = std::begin(this->binary_->dynamic_symbols_);
|
||||
const auto it_end = std::end(this->binary_->dynamic_symbols_);
|
||||
|
||||
const auto it_first_non_local_symbol =
|
||||
std::stable_partition(it_begin, it_end, [] (const Symbol* sym) {
|
||||
return sym->binding() == SYMBOL_BINDINGS::STB_LOCAL;
|
||||
});
|
||||
|
||||
const uint32_t first_non_local_symbol_index =
|
||||
std::distance(it_begin, it_first_non_local_symbol);
|
||||
|
||||
if (this->binary_->has_section(dynsym_section_name)) {
|
||||
Section& section = this->binary_->get_section(dynsym_section_name);
|
||||
if (section.information() != first_non_local_symbol_index) {
|
||||
// TODO: Erase null entries of dynamic symbol table and symbol version
|
||||
// table if information of .dynsym section is smaller than null entries
|
||||
// num.
|
||||
LIEF_WARN("information of {} section changes from {:d} to {:d}",
|
||||
dynsym_section_name,
|
||||
section.information(),
|
||||
first_non_local_symbol_index);
|
||||
section.information(first_non_local_symbol_index);
|
||||
}
|
||||
}
|
||||
|
||||
const auto it_first_exported_symbol = std::stable_partition(
|
||||
it_first_non_local_symbol, it_end, [] (const Symbol* sym) {
|
||||
return sym->shndx() ==
|
||||
static_cast<uint16_t>(SYMBOL_SECTION_INDEX::SHN_UNDEF);
|
||||
});
|
||||
|
||||
const uint32_t first_exported_symbol_index =
|
||||
std::distance(it_begin, it_first_exported_symbol);
|
||||
return first_exported_symbol_index;
|
||||
}
|
||||
|
||||
|
||||
void Builder::build_empty_symbol_gnuhash(void) {
|
||||
LIEF_DEBUG("Build empty GNU Hash");
|
||||
auto&& it_gnuhash = std::find_if(
|
||||
|
||||
+3
-19
@@ -827,12 +827,6 @@ void Builder::build_symbol_hash(void) {
|
||||
hashtable_stream.setpos(0);
|
||||
uint32_t nbucket = hashtable_stream.read_conv<uint32_t>();
|
||||
uint32_t nchain = hashtable_stream.read_conv<uint32_t>();
|
||||
if (nchain != this->binary_->dynamic_symbols_.size()) {
|
||||
LIEF_WARN("nchain of .hash section changes from {:d} to {:d}",
|
||||
nchain,
|
||||
this->binary_->dynamic_symbols_.size());
|
||||
nchain = this->binary_->dynamic_symbols_.size();
|
||||
}
|
||||
|
||||
|
||||
std::vector<uint8_t> new_hash_table((nbucket + nchain + 2) * sizeof(uint32_t), 0);
|
||||
@@ -912,7 +906,7 @@ void Builder::build_symbol_hash(void) {
|
||||
// See also:
|
||||
// * p.9, https://www.akkadia.org/drepper/dsohowto.pdf
|
||||
template<typename ELF_T>
|
||||
void Builder::build_symbol_gnuhash(uint32_t new_symndx) {
|
||||
void Builder::build_symbol_gnuhash(void) {
|
||||
using uint__ = typename ELF_T::uint;
|
||||
|
||||
LIEF_DEBUG("== Build GNU Hash table ==");
|
||||
@@ -920,16 +914,10 @@ void Builder::build_symbol_gnuhash(uint32_t new_symndx) {
|
||||
const GnuHash& gnu_hash = this->binary_->gnu_hash();
|
||||
|
||||
const uint32_t nb_buckets = gnu_hash.nb_buckets();
|
||||
const uint32_t symndx = new_symndx;
|
||||
const uint32_t symndx = gnu_hash.symbol_index();
|
||||
const uint32_t maskwords = gnu_hash.maskwords();
|
||||
const uint32_t shift2 = gnu_hash.shift2();
|
||||
|
||||
if (symndx != gnu_hash.symbol_index()) {
|
||||
LIEF_WARN("symndx of .gnu.hash section changes from {:d} to {:d}",
|
||||
gnu_hash.symbol_index(),
|
||||
symndx);
|
||||
}
|
||||
|
||||
const std::vector<uint64_t>& filters = gnu_hash.bloom_filters();
|
||||
if (filters.size() > 0 and filters[0] == 0) {
|
||||
LIEF_DEBUG("Bloom filter is null");
|
||||
@@ -1099,10 +1087,6 @@ void Builder::build_hash_table(void) {
|
||||
{
|
||||
return section != nullptr and section->type() == ELF_SECTION_TYPES::SHT_GNU_HASH;
|
||||
});
|
||||
uint32_t new_symndx = 0;
|
||||
if (it_gnuhash != std::end(this->binary_->sections_)) {
|
||||
new_symndx = sort_dynamic_symbols();
|
||||
}
|
||||
|
||||
//TODO: To improve
|
||||
if (it_hash != std::end(this->binary_->sections_)) {
|
||||
@@ -1113,7 +1097,7 @@ void Builder::build_hash_table(void) {
|
||||
if (this->empties_gnuhash_) {
|
||||
this->build_empty_symbol_gnuhash();
|
||||
} else {
|
||||
this->build_symbol_gnuhash<ELF_T>(new_symndx);
|
||||
this->build_symbol_gnuhash<ELF_T>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,6 @@
|
||||
|
||||
#include "logging.hpp"
|
||||
|
||||
#include "LIEF/BinaryStream/MemoryStream.hpp"
|
||||
#include "LIEF/BinaryStream/VectorStream.hpp"
|
||||
|
||||
#include "LIEF/ELF/DataHandler/Handler.hpp"
|
||||
#include "LIEF/exception.hpp"
|
||||
|
||||
@@ -42,30 +39,6 @@ Handler::Handler(std::vector<uint8_t>&& content) :
|
||||
data_{std::move(content)}
|
||||
{}
|
||||
|
||||
Handler::Handler(BinaryStream& stream) {
|
||||
|
||||
switch (stream.type()) {
|
||||
case BinaryStream::STREAM_TYPE::FILE:
|
||||
{
|
||||
auto& vs = reinterpret_cast<VectorStream&>(stream);
|
||||
data_ = vs.content();
|
||||
break;
|
||||
}
|
||||
|
||||
case BinaryStream::STREAM_TYPE::MEMORY:
|
||||
{
|
||||
throw std::runtime_error("Not impletemented yet");
|
||||
break;
|
||||
}
|
||||
|
||||
case BinaryStream::STREAM_TYPE::UNKNOWN:
|
||||
default:
|
||||
{
|
||||
LIEF_ERR("Unknown stream type!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<uint8_t>& Handler::content(void) const {
|
||||
return this->data_;
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ const char* to_string(VERSION e) {
|
||||
|
||||
|
||||
const char* to_string(ARCH e) {
|
||||
CONST_MAP(ARCH, const char*, 177) enumStrings {
|
||||
CONST_MAP(ARCH, const char*, 176) enumStrings {
|
||||
{ ARCH::EM_NONE, "None" },
|
||||
{ ARCH::EM_M32, "M32"},
|
||||
{ ARCH::EM_SPARC, "SPARC"},
|
||||
@@ -236,7 +236,6 @@ const char* to_string(ARCH e) {
|
||||
{ ARCH::EM_NORC, "NORC"},
|
||||
{ ARCH::EM_CSR_KALIMBA, "CSR_KALIMBA"},
|
||||
{ ARCH::EM_AMDGPU, "AMDGPU"},
|
||||
{ ARCH::EM_RISCV, "RISCV"},
|
||||
{ ARCH::EM_BPF, "BPF"}
|
||||
};
|
||||
auto it = enumStrings.find(e);
|
||||
|
||||
+1
-1
@@ -121,7 +121,7 @@ void Parser::init(const std::string& name) {
|
||||
try {
|
||||
this->binary_->original_size_ = this->binary_size_;
|
||||
this->binary_->name(name);
|
||||
this->binary_->datahandler_ = new DataHandler::Handler{*stream_};
|
||||
this->binary_->datahandler_ = new DataHandler::Handler{this->stream_->content()};
|
||||
|
||||
const Elf32_Ehdr& elf_hdr = this->stream_->peek<Elf32_Ehdr>(0);
|
||||
this->stream_->set_endian_swap(this->should_swap());
|
||||
|
||||
+2
-14
@@ -1112,7 +1112,6 @@ void Parser::parse_dynamic_entries(uint64_t offset, uint64_t size) {
|
||||
|
||||
Elf_Off dynamic_string_offset = this->get_dynamic_string_table();
|
||||
|
||||
bool end_of_dynamic = false;
|
||||
this->stream_->setpos(offset);
|
||||
for (size_t dynIdx = 0; dynIdx < nb_entries; ++dynIdx) {
|
||||
if (not this->stream_->can_read<Elf_Dyn>()) {
|
||||
@@ -1191,13 +1190,6 @@ void Parser::parse_dynamic_entries(uint64_t offset, uint64_t size) {
|
||||
break;
|
||||
}
|
||||
|
||||
case DYNAMIC_TAGS::DT_NULL:
|
||||
{
|
||||
dynamic_entry = std::unique_ptr<DynamicEntry>{new DynamicEntry{&entry}};
|
||||
end_of_dynamic = true;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
dynamic_entry = std::unique_ptr<DynamicEntry>{new DynamicEntry{&entry}};
|
||||
@@ -1210,10 +1202,6 @@ void Parser::parse_dynamic_entries(uint64_t offset, uint64_t size) {
|
||||
LIEF_WARN("dynamic_entry is nullptr !");
|
||||
}
|
||||
|
||||
if (end_of_dynamic) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Check for INIT array
|
||||
@@ -1621,7 +1609,7 @@ void Parser::parse_symbol_gnu_hash(uint64_t offset) {
|
||||
|
||||
static constexpr uint32_t NB_MAX_WORDS = 90000;
|
||||
static constexpr uint32_t NB_MAX_BUCKETS = 90000;
|
||||
static constexpr uint32_t MAX_NB_HASH = 1000000;
|
||||
static constexpr uint32_t MAX_NB_HASH = 90000;
|
||||
|
||||
LIEF_DEBUG("== Parser symbol GNU hash ==");
|
||||
GnuHash gnuhash;
|
||||
@@ -1698,7 +1686,7 @@ void Parser::parse_symbol_gnu_hash(uint64_t offset) {
|
||||
gnuhash.hash_values_ = std::move(hashvalues);
|
||||
}
|
||||
} else {
|
||||
LIEF_ERR("The number of hash entries seems too high ({:d})", nb_hash);
|
||||
LIEF_ERR("GNU Hash, nb_hash corrupted");
|
||||
}
|
||||
}
|
||||
this->binary_->gnu_hash_ = std::move(gnuhash);
|
||||
|
||||
+190
-199
@@ -74,7 +74,8 @@ LIEF::sections_t Binary::get_abstract_sections(void) {
|
||||
LIEF::sections_t result;
|
||||
it_sections sections = this->sections();
|
||||
std::transform(
|
||||
std::begin(sections), std::end(sections),
|
||||
std::begin(sections),
|
||||
std::end(sections),
|
||||
std::back_inserter(result),
|
||||
[] (Section& s) {
|
||||
return &s;
|
||||
@@ -95,7 +96,8 @@ void Binary::patch_address(uint64_t address, const std::vector<uint8_t>& patch_v
|
||||
const uint64_t offset = address - segment_topatch->virtual_address();
|
||||
std::vector<uint8_t> content = segment_topatch->content();
|
||||
std::copy(
|
||||
std::begin(patch_value), std::end(patch_value),
|
||||
std::begin(patch_value),
|
||||
std::end(patch_value),
|
||||
content.data() + offset);
|
||||
segment_topatch->content(content);
|
||||
|
||||
@@ -117,7 +119,8 @@ void Binary::patch_address(uint64_t address, uint64_t patch_value, size_t size,
|
||||
std::vector<uint8_t> content = segment_topatch->content();
|
||||
|
||||
std::copy(
|
||||
reinterpret_cast<uint8_t*>(&patch_value), reinterpret_cast<uint8_t*>(&patch_value) + size,
|
||||
reinterpret_cast<uint8_t*>(&patch_value),
|
||||
reinterpret_cast<uint8_t*>(&patch_value) + size,
|
||||
content.data() + offset);
|
||||
segment_topatch->content(content);
|
||||
|
||||
@@ -186,7 +189,8 @@ LIEF::Binary::functions_t Binary::get_abstract_exported_functions(void) const {
|
||||
LIEF::Binary::functions_t result;
|
||||
it_const_exported_symbols syms = this->exported_symbols();
|
||||
std::transform(
|
||||
std::begin(syms), std::end(syms),
|
||||
std::begin(syms),
|
||||
std::end(syms),
|
||||
std::back_inserter(result),
|
||||
[] (const Symbol& s) {
|
||||
return Function{s.name(), s.value(), Function::flags_list_t{Function::FLAGS::EXPORTED}};
|
||||
@@ -198,7 +202,8 @@ LIEF::Binary::functions_t Binary::get_abstract_imported_functions(void) const {
|
||||
LIEF::Binary::functions_t result;
|
||||
it_const_imported_symbols syms = this->imported_symbols();
|
||||
std::transform(
|
||||
std::begin(syms), std::end(syms),
|
||||
std::begin(syms),
|
||||
std::end(syms),
|
||||
std::back_inserter(result),
|
||||
[] (const Symbol& s) {
|
||||
return Function{s.name(), s.value(), Function::flags_list_t{Function::FLAGS::IMPORTED}};
|
||||
@@ -247,27 +252,68 @@ it_const_symbols Binary::symbols(void) const {
|
||||
}
|
||||
|
||||
it_libraries Binary::libraries(void) {
|
||||
return this->libraries_;
|
||||
libraries_t result;
|
||||
|
||||
for (LoadCommand* library: this->commands_) {
|
||||
if (typeid(*library) == typeid(DylibCommand)) {
|
||||
result.push_back(dynamic_cast<DylibCommand*>(library));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
it_const_libraries Binary::libraries(void) const {
|
||||
return this->libraries_;
|
||||
|
||||
libraries_t result;
|
||||
|
||||
for (LoadCommand* library: this->commands_) {
|
||||
if (typeid(*library) == typeid(DylibCommand)) {
|
||||
result.push_back(dynamic_cast<DylibCommand*>(library));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
it_segments Binary::segments(void) {
|
||||
return this->segments_;
|
||||
segments_t result{};
|
||||
result.reserve(this->commands_.size());
|
||||
for (LoadCommand* cmd: this->commands_) {
|
||||
if (typeid(*cmd) == typeid(SegmentCommand)) {
|
||||
result.push_back(dynamic_cast<SegmentCommand*>(cmd));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
it_const_segments Binary::segments(void) const {
|
||||
return this->segments_;
|
||||
segments_t result{};
|
||||
result.reserve(this->commands_.size());
|
||||
for (LoadCommand* cmd: this->commands_) {
|
||||
if (typeid(*cmd) == typeid(SegmentCommand)) {
|
||||
result.push_back(dynamic_cast<SegmentCommand*>(cmd));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
it_sections Binary::sections(void) {
|
||||
return this->sections_;
|
||||
sections_t result;
|
||||
for (SegmentCommand& segment : this->segments()) {
|
||||
for (Section& s: segment.sections()) {
|
||||
result.push_back(&s);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
it_const_sections Binary::sections(void) const {
|
||||
return this->sections_;
|
||||
sections_t result;
|
||||
for (const SegmentCommand& segment : this->segments()) {
|
||||
for (const Section& s: segment.sections()) {
|
||||
result.push_back(const_cast<Section*>(&s));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -360,25 +406,32 @@ it_const_imported_symbols Binary::imported_symbols(void) const {
|
||||
|
||||
|
||||
bool Binary::has_symbol(const std::string& name) const {
|
||||
return this->get_symbol(name) != nullptr;
|
||||
auto&& it_symbol = std::find_if(
|
||||
std::begin(this->symbols_),
|
||||
std::end(this->symbols_),
|
||||
[&name] (const Symbol* sym) {
|
||||
return sym->name() == name;
|
||||
});
|
||||
return it_symbol != std::end(this->symbols_);
|
||||
}
|
||||
|
||||
const Symbol* Binary::get_symbol(const std::string& name) const {
|
||||
const auto it_symbol = std::find_if(
|
||||
std::begin(this->symbols_), std::end(this->symbols_),
|
||||
const Symbol& Binary::get_symbol(const std::string& name) const {
|
||||
if (not this->has_symbol(name)) {
|
||||
throw not_found("Unable to find the symbol '" + name + "'");
|
||||
}
|
||||
|
||||
auto&& it_symbol = std::find_if(
|
||||
std::begin(this->symbols_),
|
||||
std::end(this->symbols_),
|
||||
[&name] (const Symbol* sym) {
|
||||
return sym->name() == name;
|
||||
});
|
||||
|
||||
if (it_symbol == std::end(this->symbols_)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return *it_symbol;
|
||||
return *(*it_symbol);
|
||||
}
|
||||
|
||||
Symbol* Binary::get_symbol(const std::string& name) {
|
||||
return const_cast<Symbol*>(static_cast<const Binary*>(this)->get_symbol(name));
|
||||
Symbol& Binary::get_symbol(const std::string& name) {
|
||||
return const_cast<Symbol&>(static_cast<const Binary*>(this)->get_symbol(name));
|
||||
}
|
||||
|
||||
// =====
|
||||
@@ -391,9 +444,10 @@ void Binary::write(const std::string& filename) {
|
||||
|
||||
const Section* Binary::section_from_offset(uint64_t offset) const {
|
||||
it_const_sections sections = this->sections();
|
||||
const auto it_section = std::find_if(
|
||||
sections.cbegin(), sections.cend(),
|
||||
[offset] (const Section& section) {
|
||||
auto&& it_section = std::find_if(
|
||||
sections.cbegin(),
|
||||
sections.cend(),
|
||||
[&offset] (const Section& section) {
|
||||
return ((section.offset() <= offset) and
|
||||
offset < (section.offset() + section.size()));
|
||||
});
|
||||
@@ -412,14 +466,15 @@ Section* Binary::section_from_offset(uint64_t offset) {
|
||||
|
||||
const Section* Binary::section_from_virtual_address(uint64_t address) const {
|
||||
it_const_sections sections = this->sections();
|
||||
const auto it_section = std::find_if(
|
||||
std::begin(sections), std::end(sections),
|
||||
auto&& it_section = std::find_if(
|
||||
std::begin(sections),
|
||||
std::end(sections),
|
||||
[address] (const Section& section) {
|
||||
return ((section.virtual_address() <= address) and
|
||||
address < (section.virtual_address() + section.size()));
|
||||
});
|
||||
|
||||
if (it_section == std::end(sections)) {
|
||||
if (it_section == sections.cend()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -432,14 +487,15 @@ Section* Binary::section_from_virtual_address(uint64_t address) {
|
||||
|
||||
const SegmentCommand* Binary::segment_from_virtual_address(uint64_t virtual_address) const {
|
||||
it_const_segments segments = this->segments();
|
||||
auto it_segment = std::find_if(
|
||||
std::begin(segments), std::end(segments),
|
||||
[virtual_address] (const SegmentCommand& segment) {
|
||||
auto&& it_segment = std::find_if(
|
||||
std::begin(segments),
|
||||
std::end(segments),
|
||||
[&virtual_address] (const SegmentCommand& segment) {
|
||||
return ((segment.virtual_address() <= virtual_address) and
|
||||
virtual_address < (segment.virtual_address() + segment.virtual_size()));
|
||||
});
|
||||
|
||||
if (it_segment == std::end(segments)) {
|
||||
if (it_segment == segments.cend()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -447,7 +503,14 @@ const SegmentCommand* Binary::segment_from_virtual_address(uint64_t virtual_addr
|
||||
}
|
||||
|
||||
size_t Binary::segment_index(const SegmentCommand& segment) const {
|
||||
return segment.index();
|
||||
auto&& segments = this->segments();
|
||||
auto&& it = std::find_if(
|
||||
std::begin(segments),
|
||||
std::end(segments),
|
||||
[&segment] (const SegmentCommand& s) {
|
||||
return s == segment;
|
||||
});
|
||||
return std::distance(std::begin(segments), it);
|
||||
}
|
||||
|
||||
SegmentCommand* Binary::segment_from_virtual_address(uint64_t virtual_address) {
|
||||
@@ -455,22 +518,20 @@ SegmentCommand* Binary::segment_from_virtual_address(uint64_t virtual_address) {
|
||||
}
|
||||
|
||||
const SegmentCommand* Binary::segment_from_offset(uint64_t offset) const {
|
||||
const auto it_begin = std::begin(this->offset_seg_);
|
||||
if (offset < it_begin->first) {
|
||||
it_const_segments segments = this->segments();
|
||||
auto&& it_segment = std::find_if(
|
||||
std::begin(segments),
|
||||
std::end(segments),
|
||||
[&offset] (const SegmentCommand& segment) {
|
||||
return ((segment.file_offset() <= offset) and
|
||||
offset < (segment.file_offset() + segment.file_size()));
|
||||
});
|
||||
|
||||
if (it_segment == segments.cend()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto it = this->offset_seg_.lower_bound(offset);
|
||||
if (it->first == offset or it == it_begin) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
const auto it_end = this->offset_seg_.crbegin();
|
||||
if (it == std::end(this->offset_seg_) and offset >= it_end->first) {
|
||||
return it_end->second;
|
||||
}
|
||||
--it;
|
||||
return it->second;
|
||||
return &(*it_segment);
|
||||
}
|
||||
|
||||
SegmentCommand* Binary::segment_from_offset(uint64_t offset) {
|
||||
@@ -689,7 +750,6 @@ void Binary::shift(size_t value) {
|
||||
|
||||
// Shift Segment and sections
|
||||
// ==========================
|
||||
this->offset_seg_.clear();
|
||||
for (SegmentCommand& segment : this->segments()) {
|
||||
// Extend the virtual size of the segment containing our shift
|
||||
if (segment.file_offset() <= loadcommands_end and loadcommands_end < (segment.file_offset() + segment.file_size())) {
|
||||
@@ -703,6 +763,7 @@ void Binary::shift(size_t value) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
if (segment.file_offset() >= loadcommands_end) {
|
||||
segment.file_offset(segment.file_offset() + value);
|
||||
segment.virtual_address(segment.virtual_address() + value);
|
||||
@@ -719,8 +780,6 @@ void Binary::shift(size_t value) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->offset_seg_[segment.file_offset()] = &segment;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -761,7 +820,8 @@ LoadCommand& Binary::add(const LoadCommand& command) {
|
||||
|
||||
// Copy the command data
|
||||
std::copy(
|
||||
std::begin(command.data()), std::end(command.data()),
|
||||
std::begin(command.data()),
|
||||
std::end(command.data()),
|
||||
std::begin(content) + loadcommands_end);
|
||||
|
||||
load_cmd_segment->content(std::move(content));
|
||||
@@ -771,16 +831,6 @@ LoadCommand& Binary::add(const LoadCommand& command) {
|
||||
copy->command_offset(loadcommands_end);
|
||||
|
||||
this->commands_.push_back(copy);
|
||||
|
||||
// Update cache
|
||||
if (typeid(*copy) == typeid(DylibCommand)) {
|
||||
this->libraries_.push_back(reinterpret_cast<DylibCommand*>(copy));
|
||||
}
|
||||
|
||||
if (typeid(*copy) == typeid(SegmentCommand)) {
|
||||
this->add_cached_segment(*reinterpret_cast<SegmentCommand*>(copy));
|
||||
}
|
||||
|
||||
return *this->commands_.back();
|
||||
}
|
||||
|
||||
@@ -824,22 +874,15 @@ LoadCommand& Binary::add(const LoadCommand& command, size_t index) {
|
||||
}
|
||||
}
|
||||
|
||||
if (typeid(*copy) == typeid(DylibCommand)) {
|
||||
this->libraries_.push_back(reinterpret_cast<DylibCommand*>(copy));
|
||||
}
|
||||
|
||||
if (typeid(*copy) == typeid(SegmentCommand)) {
|
||||
this->add_cached_segment(*reinterpret_cast<SegmentCommand*>(copy));
|
||||
}
|
||||
|
||||
this->commands_.insert(std::begin(this->commands_) + index, copy);
|
||||
return *copy;
|
||||
}
|
||||
|
||||
bool Binary::remove(const LoadCommand& command) {
|
||||
|
||||
const auto it = std::find_if(
|
||||
std::begin(this->commands_), std::end(this->commands_),
|
||||
auto&& it = std::find_if(
|
||||
std::begin(this->commands_),
|
||||
std::end(this->commands_),
|
||||
[&command] (const LoadCommand* cmd) {
|
||||
return *cmd == command;
|
||||
});
|
||||
@@ -850,35 +893,6 @@ bool Binary::remove(const LoadCommand& command) {
|
||||
}
|
||||
|
||||
LoadCommand* cmd_rm = *it;
|
||||
|
||||
if (typeid(*cmd_rm) == typeid(DylibCommand)) {
|
||||
auto it_cache = std::find(std::begin(this->libraries_), std::end(this->libraries_), cmd_rm);
|
||||
if (it_cache == std::end(this->libraries_)) {
|
||||
const auto* lib = reinterpret_cast<const DylibCommand*>(cmd_rm);
|
||||
LIEF_WARN("Library {} not found in cache. The binary object is likely in an inconsistent state", lib->name());
|
||||
} else {
|
||||
this->libraries_.erase(it_cache);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeid(*cmd_rm) == typeid(SegmentCommand)) {
|
||||
auto it_cache = std::find(std::begin(this->segments_), std::end(this->segments_), cmd_rm);
|
||||
const auto* seg = reinterpret_cast<const SegmentCommand*>(cmd_rm);
|
||||
if (it_cache == std::end(this->segments_)) {
|
||||
LIEF_WARN("Segment {} not found in cache. The binary object is likely in an inconsistent state", seg->name());
|
||||
} else {
|
||||
// Update the indexes to keep a consistent state
|
||||
for (auto it = it_cache; it != std::end(this->segments_); ++it) {
|
||||
(*it)->index_--;
|
||||
}
|
||||
this->segments_.erase(it_cache);
|
||||
}
|
||||
auto it_offset = this->offset_seg_.find(seg->file_offset());
|
||||
if (it_offset != std::end(this->offset_seg_)) {
|
||||
this->offset_seg_.erase(it_offset);
|
||||
}
|
||||
}
|
||||
|
||||
const size_t cmd_rm_offset = cmd_rm->command_offset();
|
||||
for (LoadCommand* cmd : this->commands_) {
|
||||
if (cmd->command_offset() >= cmd_rm_offset) {
|
||||
@@ -915,8 +929,9 @@ bool Binary::remove_command(size_t index) {
|
||||
}
|
||||
|
||||
bool Binary::has(LOAD_COMMAND_TYPES type) const {
|
||||
const auto it = std::find_if(
|
||||
std::begin(this->commands_), std::end(this->commands_),
|
||||
auto&& it = std::find_if(
|
||||
std::begin(this->commands_),
|
||||
std::end(this->commands_),
|
||||
[type] (const LoadCommand* cmd) {
|
||||
return cmd->command() == type;
|
||||
});
|
||||
@@ -928,8 +943,9 @@ const LoadCommand& Binary::get(LOAD_COMMAND_TYPES type) const {
|
||||
throw not_found(std::string("Can't find '") + to_string(type) + "'");
|
||||
}
|
||||
|
||||
const auto it = std::find_if(
|
||||
std::begin(this->commands_), std::end(this->commands_),
|
||||
auto&& it = std::find_if(
|
||||
std::begin(this->commands_),
|
||||
std::end(this->commands_),
|
||||
[type] (const LoadCommand* cmd) {
|
||||
return cmd->command() == type;
|
||||
});
|
||||
@@ -943,8 +959,9 @@ LoadCommand& Binary::get(LOAD_COMMAND_TYPES type) {
|
||||
bool Binary::extend(const LoadCommand& command, uint64_t size) {
|
||||
static constexpr uint32_t shift_value = 0x10000;
|
||||
|
||||
const auto it = std::find_if(
|
||||
std::begin(this->commands_), std::end(this->commands_),
|
||||
auto&& it = std::find_if(
|
||||
std::begin(this->commands_),
|
||||
std::end(this->commands_),
|
||||
[&command] (const LoadCommand* cmd) {
|
||||
return *cmd == command;
|
||||
});
|
||||
@@ -982,9 +999,10 @@ bool Binary::extend(const LoadCommand& command, uint64_t size) {
|
||||
|
||||
bool Binary::extend_segment(const SegmentCommand& segment, size_t size) {
|
||||
|
||||
it_segments segments = this->segments();
|
||||
const auto it_segment = std::find_if(
|
||||
std::begin(segments), std::end(segments),
|
||||
auto&& segments = this->segments();
|
||||
auto&& it_segment = std::find_if(
|
||||
std::begin(segments),
|
||||
std::end(segments),
|
||||
[&segment] (const SegmentCommand& s) {
|
||||
return segment == s;
|
||||
});
|
||||
@@ -1042,9 +1060,11 @@ void Binary::remove_section(const std::string& name, bool clear) {
|
||||
sec_to_delete.clear(0);
|
||||
}
|
||||
|
||||
|
||||
segment.numberof_sections(segment.numberof_sections() - 1);
|
||||
auto it_section = std::find_if(
|
||||
std::begin(segment.sections_), std::end(segment.sections_),
|
||||
auto&& it_section = std::find_if(
|
||||
std::begin(segment.sections_),
|
||||
std::end(segment.sections_),
|
||||
[&sec_to_delete] (const Section* s) {
|
||||
return *s == sec_to_delete;
|
||||
});
|
||||
@@ -1067,17 +1087,9 @@ void Binary::remove_section(const std::string& name, bool clear) {
|
||||
|
||||
this->available_command_space_ += section_struct_size;
|
||||
|
||||
Section* section = *it_section;
|
||||
// Remove from cache
|
||||
auto it_cache = std::find(std::begin(this->sections_), std::end(this->sections_), section);
|
||||
if (it_cache == std::end(this->sections_)) {
|
||||
LIEF_WARN("Can find the section {} in the cache. The binary object is likely in an inconsistent state",
|
||||
section->name());
|
||||
} else {
|
||||
this->sections_.erase(it_cache);
|
||||
}
|
||||
|
||||
delete section;
|
||||
|
||||
delete *it_section;
|
||||
segment.sections_.erase(it_section);
|
||||
}
|
||||
|
||||
@@ -1093,9 +1105,10 @@ Section* Binary::add_section(const Section& section) {
|
||||
|
||||
Section* Binary::add_section(const SegmentCommand& segment, const Section& section) {
|
||||
|
||||
it_segments segments = this->segments();
|
||||
const auto it_segment = std::find_if(
|
||||
std::begin(segments), std::end(segments),
|
||||
auto&& segments = this->segments();
|
||||
auto&& it_segment = std::find_if(
|
||||
std::begin(segments),
|
||||
std::end(segments),
|
||||
[&segment] (const SegmentCommand& s) {
|
||||
return segment == s;
|
||||
});
|
||||
@@ -1130,6 +1143,7 @@ Section* Binary::add_section(const SegmentCommand& segment, const Section& secti
|
||||
|
||||
// Section raw data will be located just after commands table
|
||||
if (section.offset() == 0) {
|
||||
|
||||
uint64_t new_offset = this->is64_ ? sizeof(mach_header_64) : sizeof(mach_header);
|
||||
new_offset += this->header().sizeof_cmds();
|
||||
new_offset += this->available_command_space_;
|
||||
@@ -1148,14 +1162,12 @@ Section* Binary::add_section(const SegmentCommand& segment, const Section& secti
|
||||
target_segment.sections_.push_back(new_section);
|
||||
target_segment.numberof_sections(target_segment.numberof_sections() + 1);
|
||||
|
||||
// Copy the new section in the cache
|
||||
this->sections_.push_back(new_section);
|
||||
|
||||
// Copy data to segment
|
||||
const size_t relative_offset = new_section->offset() - target_segment.file_offset();
|
||||
|
||||
std::move(
|
||||
std::begin(content), std::end(content),
|
||||
std::begin(content),
|
||||
std::end(content),
|
||||
std::begin(target_segment.data_) + relative_offset);
|
||||
|
||||
return new_section;
|
||||
@@ -1196,8 +1208,9 @@ LoadCommand& Binary::add(const SegmentCommand& segment) {
|
||||
|
||||
|
||||
// Insert the segment before __LINKEDIT
|
||||
const auto it_linkedit = std::find_if(
|
||||
std::begin(this->commands_), std::end(this->commands_),
|
||||
auto&& it_linkedit = std::find_if(
|
||||
std::begin(this->commands_),
|
||||
std::end(this->commands_),
|
||||
[] (const LoadCommand* cmd) {
|
||||
if (not cmd->is<SegmentCommand>()) {
|
||||
return false;
|
||||
@@ -1240,34 +1253,12 @@ LoadCommand& Binary::add(const SegmentCommand& segment) {
|
||||
return segment_added;
|
||||
}
|
||||
|
||||
size_t Binary::add_cached_segment(SegmentCommand& segment) {
|
||||
// The new segement should be put **befor** the __LINKEDIT
|
||||
// segment
|
||||
const auto it_linkedit = std::find_if(std::begin(this->segments_), std::end(this->segments_),
|
||||
[] (SegmentCommand* cmd) { return cmd->name() == "__LINKEDIT"; });
|
||||
|
||||
if (it_linkedit == std::end(this->segments_)) {
|
||||
LIEF_DEBUG("No __LINKEDIT segment found!");
|
||||
segment.index_ = this->segments_.size();
|
||||
this->segments_.push_back(&segment);
|
||||
}
|
||||
segment.index_ = (*it_linkedit)->index();
|
||||
|
||||
// Update indexes
|
||||
for (auto it = it_linkedit; it != std::end(this->segments_); ++it) {
|
||||
(*it)->index_++;
|
||||
}
|
||||
this->segments_.insert(it_linkedit, &segment);
|
||||
this->offset_seg_[segment.file_offset()] = &segment;
|
||||
return segment.index();
|
||||
}
|
||||
|
||||
bool Binary::unexport(const std::string& name) {
|
||||
const Symbol* s = this->get_symbol(name);
|
||||
if (s == nullptr) {
|
||||
if (not this->has_symbol(name)) {
|
||||
return false;
|
||||
}
|
||||
return this->unexport(*s);
|
||||
const Symbol& s = this->get_symbol(name);
|
||||
return this->unexport(s);
|
||||
}
|
||||
|
||||
bool Binary::unexport(const Symbol& sym) {
|
||||
@@ -1276,8 +1267,9 @@ bool Binary::unexport(const Symbol& sym) {
|
||||
}
|
||||
|
||||
DyldInfo& dyld = this->dyld_info();
|
||||
const auto it_export = std::find_if(
|
||||
std::begin(dyld.export_info_), std::end(dyld.export_info_),
|
||||
auto&& it_export = std::find_if(
|
||||
std::begin(dyld.export_info_),
|
||||
std::end(dyld.export_info_),
|
||||
[&sym] (const ExportInfo* info) {
|
||||
return info->has_symbol() and info->symbol() == sym;
|
||||
});
|
||||
@@ -1297,8 +1289,9 @@ bool Binary::unexport(const Symbol& sym) {
|
||||
bool Binary::remove(const Symbol& sym) {
|
||||
/* bool export_removed = */ this->unexport(sym);
|
||||
|
||||
const auto it_symbol = std::find_if(
|
||||
std::begin(this->symbols_), std::end(this->symbols_),
|
||||
auto&& it_symbol = std::find_if(
|
||||
std::begin(this->symbols_),
|
||||
std::end(this->symbols_),
|
||||
[&sym] (const Symbol* s) {
|
||||
return s->name() == sym.name();
|
||||
});
|
||||
@@ -1334,8 +1327,9 @@ bool Binary::remove(const Symbol& sym) {
|
||||
symtab.push_back(s);
|
||||
}
|
||||
}
|
||||
const auto it_symtab = std::find_if(
|
||||
std::begin(symtab), std::end(symtab),
|
||||
auto&& it_symtab = std::find_if(
|
||||
std::begin(symtab),
|
||||
std::end(symtab),
|
||||
[symbol_to_remove] (const Symbol* symtab_sym) {
|
||||
return *symbol_to_remove == *symtab_sym;
|
||||
});
|
||||
@@ -1412,12 +1406,12 @@ bool Binary::remove(const Symbol& sym) {
|
||||
|
||||
bool Binary::remove_symbol(const std::string& name) {
|
||||
bool removed = false;
|
||||
const Symbol* s = this->get_symbol(name);
|
||||
while (s != nullptr) {
|
||||
if (not this->remove(*s)) {
|
||||
while (this->has_symbol(name)) {
|
||||
const Symbol& s = this->get_symbol(name);
|
||||
if (not this->remove(s)) {
|
||||
break;
|
||||
}
|
||||
s = this->get_symbol(name);
|
||||
|
||||
removed = true;
|
||||
}
|
||||
return removed;
|
||||
@@ -1431,7 +1425,7 @@ bool Binary::can_remove(const Symbol& sym) const {
|
||||
}
|
||||
|
||||
const DyldInfo& dyld = this->dyld_info();
|
||||
it_const_binding_info bindings = dyld.bindings();
|
||||
auto&& bindings = dyld.bindings();
|
||||
|
||||
for (const BindingInfo& binding : bindings) {
|
||||
if (binding.has_symbol() and binding.symbol().name() == sym.name()) {
|
||||
@@ -1490,20 +1484,6 @@ uint64_t Binary::virtual_address_to_offset(uint64_t virtual_address) const {
|
||||
return virtual_address - base_address;
|
||||
}
|
||||
|
||||
uint64_t Binary::offset_to_virtual_address(uint64_t offset, uint64_t slide) const {
|
||||
const SegmentCommand* segment = this->segment_from_offset(offset);
|
||||
if (segment == nullptr) {
|
||||
return offset + slide;
|
||||
}
|
||||
const uint64_t base_address = segment->virtual_address() - segment->file_offset();
|
||||
if (slide > 0) {
|
||||
if (this->imagebase() == 0) {
|
||||
return slide + offset;
|
||||
}
|
||||
return (base_address - this->imagebase()) + offset + slide;
|
||||
}
|
||||
return base_address + offset;
|
||||
}
|
||||
|
||||
bool Binary::disable_pie(void) {
|
||||
if (this->is_pie()) {
|
||||
@@ -1518,13 +1498,14 @@ bool Binary::disable_pie(void) {
|
||||
bool Binary::has_section(const std::string& name) const {
|
||||
it_const_sections sections = this->sections();
|
||||
|
||||
const auto it_section = std::find_if(
|
||||
std::begin(sections), std::end(sections),
|
||||
auto&& it_section = std::find_if(
|
||||
std::begin(sections),
|
||||
std::end(sections),
|
||||
[&name] (const Section& sec) {
|
||||
return sec.name() == name;
|
||||
});
|
||||
|
||||
return it_section != std::end(sections);
|
||||
return it_section != sections.cend();
|
||||
}
|
||||
|
||||
Section& Binary::get_section(const std::string& name) {
|
||||
@@ -1536,8 +1517,9 @@ const Section& Binary::get_section(const std::string& name) const {
|
||||
throw not_found("'" + name + "' not found in the binary");
|
||||
}
|
||||
it_const_sections sections = this->sections();
|
||||
const auto it_section = std::find_if(
|
||||
std::begin(sections), std::end(sections),
|
||||
auto&& it_section = std::find_if(
|
||||
std::begin(sections),
|
||||
std::end(sections),
|
||||
[&name] (const Section& sec) {
|
||||
return sec.name() == name;
|
||||
});
|
||||
@@ -1548,8 +1530,9 @@ const Section& Binary::get_section(const std::string& name) const {
|
||||
bool Binary::has_segment(const std::string& name) const {
|
||||
it_const_segments segments = this->segments();
|
||||
|
||||
const auto it_segment = std::find_if(
|
||||
std::begin(segments), std::end(segments),
|
||||
auto&& it_segment = std::find_if(
|
||||
std::begin(segments),
|
||||
std::end(segments),
|
||||
[&name] (const SegmentCommand& seg) {
|
||||
return seg.name() == name;
|
||||
});
|
||||
@@ -1562,8 +1545,9 @@ const SegmentCommand* Binary::get_segment(const std::string& name) const {
|
||||
}
|
||||
|
||||
it_const_segments segments = this->segments();
|
||||
const auto it_segment = std::find_if(
|
||||
std::begin(segments), std::end(segments),
|
||||
auto&& it_segment = std::find_if(
|
||||
std::begin(segments),
|
||||
std::end(segments),
|
||||
[&name] (const SegmentCommand& seg) {
|
||||
return seg.name() == name;
|
||||
});
|
||||
@@ -1586,13 +1570,14 @@ uint64_t Binary::virtual_size(void) const {
|
||||
|
||||
uint64_t Binary::imagebase(void) const {
|
||||
it_const_segments segments = this->segments();
|
||||
auto it_text_segment = std::find_if(
|
||||
std::begin(segments), std::end(segments),
|
||||
auto&& it_text_segment = std::find_if(
|
||||
std::begin(segments),
|
||||
std::end(segments),
|
||||
[] (const SegmentCommand& segment) {
|
||||
return segment.name() == "__TEXT";
|
||||
});
|
||||
|
||||
if (it_text_segment == std::end(segments)) {
|
||||
if (it_text_segment == segments.cend()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1618,7 +1603,7 @@ bool Binary::is_valid_addr(uint64_t address) const {
|
||||
Binary::range_t Binary::va_ranges(void) const {
|
||||
|
||||
it_const_segments segments = this->segments();
|
||||
const auto it_min = std::min_element(
|
||||
auto&& it_min = std::min_element(
|
||||
std::begin(segments), std::end(segments),
|
||||
[] (const SegmentCommand& lhs, const SegmentCommand& rhs) {
|
||||
if (lhs.virtual_address() == 0 or rhs.virtual_address() == 0) {
|
||||
@@ -1628,7 +1613,7 @@ Binary::range_t Binary::va_ranges(void) const {
|
||||
});
|
||||
|
||||
|
||||
const auto it_max = std::min_element(
|
||||
auto&& it_max = std::min_element(
|
||||
std::begin(segments), std::end(segments),
|
||||
[] (const SegmentCommand& lhs, const SegmentCommand& rhs) {
|
||||
return (lhs.virtual_address() + lhs.virtual_size()) > (rhs.virtual_address() + rhs.virtual_size());
|
||||
@@ -1640,7 +1625,7 @@ Binary::range_t Binary::va_ranges(void) const {
|
||||
Binary::range_t Binary::off_ranges(void) const {
|
||||
|
||||
it_const_segments segments = this->segments();
|
||||
const auto it_min = std::min_element(
|
||||
auto&& it_min = std::min_element(
|
||||
std::begin(segments), std::end(segments),
|
||||
[] (const SegmentCommand& lhs, const SegmentCommand& rhs) {
|
||||
if (lhs.file_offset() == 0 or rhs.file_offset() == 0) {
|
||||
@@ -1650,7 +1635,7 @@ Binary::range_t Binary::off_ranges(void) const {
|
||||
});
|
||||
|
||||
|
||||
const auto it_max = std::min_element(
|
||||
auto&& it_max = std::min_element(
|
||||
std::begin(segments), std::end(segments),
|
||||
[] (const SegmentCommand& lhs, const SegmentCommand& rhs) {
|
||||
return (lhs.file_offset() + lhs.file_size()) > (rhs.file_offset() + rhs.file_size());
|
||||
@@ -1723,16 +1708,19 @@ LIEF::Binary::functions_t Binary::functions(void) const {
|
||||
LIEF::Binary::functions_t exported = this->get_abstract_exported_functions();
|
||||
|
||||
std::move(
|
||||
std::begin(unwind_functions), std::end(unwind_functions),
|
||||
std::begin(unwind_functions),
|
||||
std::end(unwind_functions),
|
||||
std::inserter(functions_set, std::end(functions_set)));
|
||||
|
||||
std::move(
|
||||
std::begin(ctor_functions), std::end(ctor_functions),
|
||||
std::begin(ctor_functions),
|
||||
std::end(ctor_functions),
|
||||
std::inserter(functions_set, std::end(functions_set)));
|
||||
|
||||
|
||||
std::move(
|
||||
std::begin(exported), std::end(exported),
|
||||
std::begin(exported),
|
||||
std::end(exported),
|
||||
std::inserter(functions_set, std::end(functions_set)));
|
||||
|
||||
return {std::begin(functions_set), std::end(functions_set)};
|
||||
@@ -1820,7 +1808,10 @@ LIEF::Binary::functions_t Binary::unwind_functions(void) const {
|
||||
functions.emplace(hdr.function_offset);
|
||||
}
|
||||
|
||||
return {std::begin(functions), std::end(functions)};
|
||||
return {
|
||||
std::begin(functions),
|
||||
std::end(functions)
|
||||
};
|
||||
}
|
||||
|
||||
// UUID
|
||||
|
||||
+17
-10
@@ -25,8 +25,9 @@ namespace MachO {
|
||||
template<class T>
|
||||
bool Binary::has_command(void) const {
|
||||
static_assert(std::is_base_of<LoadCommand, T>::value, "Require inheritance of 'LoadCommand'");
|
||||
const auto it_cmd = std::find_if(
|
||||
std::begin(this->commands_), std::end(this->commands_),
|
||||
auto&& it_cmd = std::find_if(
|
||||
std::begin(this->commands_),
|
||||
std::end(this->commands_),
|
||||
[] (const LoadCommand* command) {
|
||||
return typeid(T) == typeid(*command);
|
||||
});
|
||||
@@ -42,17 +43,22 @@ T& Binary::command(void) {
|
||||
template<class T>
|
||||
const T& Binary::command(void) const {
|
||||
static_assert(std::is_base_of<LoadCommand, T>::value, "Require inheritance of 'LoadCommand'");
|
||||
const auto it_cmd = std::find_if(
|
||||
std::begin(this->commands_), std::end(this->commands_),
|
||||
if (not this->has_command<T>()) {
|
||||
throw not_found("Unable to find the " + std::string(typeid(T).name()));
|
||||
}
|
||||
|
||||
if (this->count_commands<T>() > 1) {
|
||||
LIEF_WARN("Multiple {} command. Return the first one!", std::string(typeid(T).name()));
|
||||
}
|
||||
|
||||
auto&& it_cmd = std::find_if(
|
||||
std::begin(this->commands_),
|
||||
std::end(this->commands_),
|
||||
[] (const LoadCommand* command) {
|
||||
return typeid(T) == typeid(*command);
|
||||
});
|
||||
|
||||
if (it_cmd == std::end(this->commands_)) {
|
||||
throw not_found("Unable to find the " + std::string(typeid(T).name()));
|
||||
}
|
||||
|
||||
return *reinterpret_cast<T*>(*it_cmd);
|
||||
return *dynamic_cast<T*>(*it_cmd);
|
||||
|
||||
}
|
||||
|
||||
@@ -61,7 +67,8 @@ size_t Binary::count_commands(void) const {
|
||||
static_assert(std::is_base_of<LoadCommand, T>::value, "Require inheritance of 'LoadCommand'");
|
||||
|
||||
size_t nb_cmd = std::count_if(
|
||||
std::begin(this->commands_), std::end(this->commands_),
|
||||
std::begin(this->commands_),
|
||||
std::end(this->commands_),
|
||||
[] (const LoadCommand* command) {
|
||||
return typeid(T) == typeid(*command);
|
||||
});
|
||||
|
||||
@@ -55,7 +55,7 @@ BinaryParser::BinaryParser(const std::vector<uint8_t>& data, uint64_t fat_offset
|
||||
}
|
||||
|
||||
|
||||
BinaryParser::BinaryParser(std::unique_ptr<BinaryStream>&& stream, uint64_t fat_offset, const ParserConfig& conf) :
|
||||
BinaryParser::BinaryParser(std::unique_ptr<VectorStream>&& stream, uint64_t fat_offset, const ParserConfig& conf) :
|
||||
stream_{std::move(stream)},
|
||||
binary_{new Binary{}},
|
||||
config_{conf}
|
||||
@@ -137,16 +137,10 @@ void BinaryParser::parse_export_trie(uint64_t start, uint64_t end, const std::st
|
||||
|
||||
const std::string& symbol_name = prefix;
|
||||
std::unique_ptr<ExportInfo> export_info{new ExportInfo{0, flags, offset}};
|
||||
Symbol* symbol = nullptr;
|
||||
auto search = this->memoized_symbols_.find(symbol_name);
|
||||
if (search != this->memoized_symbols_.end()) {
|
||||
symbol = search->second;
|
||||
} else {
|
||||
symbol = this->binary_->get_symbol(symbol_name);
|
||||
}
|
||||
if (symbol != nullptr) {
|
||||
export_info->symbol_ = symbol;
|
||||
symbol->export_info_ = export_info.get();
|
||||
if (this->binary_->has_symbol(symbol_name)) {
|
||||
Symbol& symbol = this->binary_->get_symbol(symbol_name);
|
||||
export_info->symbol_ = &symbol;
|
||||
symbol.export_info_ = export_info.get();
|
||||
} else { // Register it into the symbol table
|
||||
std::unique_ptr<Symbol> symbol{new Symbol{}};
|
||||
symbol->origin_ = SYMBOL_ORIGINS::SYM_ORIGIN_DYLD_EXPORT;
|
||||
@@ -173,16 +167,10 @@ void BinaryParser::parse_export_trie(uint64_t start, uint64_t end, const std::st
|
||||
imported_name = export_info->symbol().name();
|
||||
}
|
||||
|
||||
Symbol* symbol = nullptr;
|
||||
auto search = this->memoized_symbols_.find(imported_name);
|
||||
if (search != this->memoized_symbols_.end()) {
|
||||
symbol = search->second;
|
||||
} else {
|
||||
symbol = this->binary_->get_symbol(imported_name);
|
||||
}
|
||||
if (symbol != nullptr) {
|
||||
export_info->alias_ = symbol;
|
||||
symbol->export_info_ = export_info.get();
|
||||
if (this->binary_->has_symbol(imported_name)) {
|
||||
Symbol& symbol = this->binary_->get_symbol(imported_name);
|
||||
export_info->alias_ = &symbol;
|
||||
symbol.export_info_ = export_info.get();
|
||||
} else {
|
||||
std::unique_ptr<Symbol> symbol{new Symbol{}};
|
||||
symbol->origin_ = SYMBOL_ORIGINS::SYM_ORIGIN_DYLD_EXPORT;
|
||||
|
||||
+61
-150
@@ -53,18 +53,6 @@
|
||||
namespace LIEF {
|
||||
namespace MachO {
|
||||
|
||||
namespace {
|
||||
struct ThreadedBindData {
|
||||
std::string symbol_name;
|
||||
int64_t addend = 0;
|
||||
int64_t library_ordinal = 0;
|
||||
uint8_t symbol_flags = 0;
|
||||
uint8_t type = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class MACHO_T>
|
||||
void BinaryParser::parse(void) {
|
||||
this->parse_header<MACHO_T>();
|
||||
@@ -153,10 +141,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
|
||||
local_offset += sizeof(segment_command_t);
|
||||
|
||||
SegmentCommand* segment = reinterpret_cast<SegmentCommand*>(load_command.get());
|
||||
segment->index_ = this->binary_->segments_.size();
|
||||
this->binary_->offset_seg_[segment->file_offset()] = segment;
|
||||
this->binary_->segments_.push_back(segment);
|
||||
SegmentCommand* segment = dynamic_cast<SegmentCommand*>(load_command.get());
|
||||
|
||||
const uint8_t* content = this->stream_->peek_array<uint8_t>(segment->file_offset(), segment->file_size(), /* check */ false);
|
||||
if (content != nullptr) {
|
||||
@@ -174,7 +159,6 @@ void BinaryParser::parse_load_commands(void) {
|
||||
for (size_t j = 0; j < segment->numberof_sections(); ++j) {
|
||||
const section_t* section_header = &this->stream_->peek<section_t>(local_offset);
|
||||
std::unique_ptr<Section> section{new Section{section_header}};
|
||||
this->binary_->sections_.push_back(section.get());
|
||||
if (section->size_ > 0 and
|
||||
section->type() != MACHO_SECTION_TYPES::S_ZEROFILL and
|
||||
section->type() != MACHO_SECTION_TYPES::S_THREAD_LOCAL_ZEROFILL and
|
||||
@@ -211,9 +195,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
const uint32_t str_name_offset = cmd->dylib.name;
|
||||
std::string name = this->stream_->peek_string_at(loadcommands_offset + str_name_offset);
|
||||
|
||||
auto* lib = reinterpret_cast<DylibCommand*>(load_command.get());
|
||||
lib->name(std::move(name));
|
||||
this->binary_->libraries_.push_back(lib);
|
||||
dynamic_cast<DylibCommand*>(load_command.get())->name(name);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -228,7 +210,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
const uint32_t str_path_offset = cmd->path;
|
||||
std::string path = this->stream_->peek_string_at(loadcommands_offset + str_path_offset);
|
||||
|
||||
reinterpret_cast<RPathCommand*>(load_command.get())->path(path);
|
||||
dynamic_cast<RPathCommand*>(load_command.get())->path(path);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -257,7 +239,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
linker_name_offset);
|
||||
|
||||
load_command = std::unique_ptr<DylinkerCommand>{new DylinkerCommand{cmd}};
|
||||
reinterpret_cast<DylinkerCommand*>(load_command.get())->name(name);
|
||||
dynamic_cast<DylinkerCommand*>(load_command.get())->name(name);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -292,7 +274,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
const thread_command* cmd = &this->stream_->peek<thread_command>(loadcommands_offset);
|
||||
load_command = std::unique_ptr<ThreadCommand>{new ThreadCommand{cmd}};
|
||||
|
||||
ThreadCommand* thread = reinterpret_cast<ThreadCommand*>(load_command.get());
|
||||
ThreadCommand* thread = dynamic_cast<ThreadCommand*>(load_command.get());
|
||||
thread->architecture_ = this->binary_->header().cpu_type();
|
||||
LIEF_DEBUG("FLAVOR: {} | COUNT: {}", cmd->flavor, cmd->count);
|
||||
switch(this->binary_->header().cpu_type()) {
|
||||
@@ -381,10 +363,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
symbol->name(
|
||||
this->stream_->peek_string_at(cmd->stroff + idx));
|
||||
}
|
||||
Symbol* symbol_ptr = symbol.release();
|
||||
this->binary_->symbols_.push_back(symbol_ptr);
|
||||
this->memoized_symbols_[symbol_ptr->name()] = symbol_ptr;
|
||||
this->memoized_symbols_by_address_[symbol_ptr->value()] = symbol_ptr;
|
||||
this->binary_->symbols_.push_back(symbol.release());
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -412,7 +391,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
const dyld_info_command* cmd = &this->stream_->peek<dyld_info_command>(loadcommands_offset);
|
||||
|
||||
load_command = std::unique_ptr<DyldInfo>{new DyldInfo{cmd}};
|
||||
reinterpret_cast<DyldInfo*>(load_command.get())->binary_ = this->binary_;
|
||||
dynamic_cast<DyldInfo*>(load_command.get())->binary_ = this->binary_;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -526,7 +505,7 @@ void BinaryParser::parse_load_commands(void) {
|
||||
load_command = std::unique_ptr<FunctionStarts>{new FunctionStarts{cmd}};
|
||||
|
||||
uint64_t value = 0;
|
||||
FunctionStarts* fstart = reinterpret_cast<FunctionStarts*>(load_command.get());
|
||||
FunctionStarts* fstart = dynamic_cast<FunctionStarts*>(load_command.get());
|
||||
this->stream_->setpos(cmd->dataoff);
|
||||
|
||||
do {
|
||||
@@ -806,7 +785,7 @@ void BinaryParser::parse_dyldinfo_rebases() {
|
||||
case REBASE_OPCODES::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
|
||||
{
|
||||
for (size_t i = 0; i < imm; ++i) {
|
||||
this->do_rebase<MACHO_T>(type, segment_index, segment_offset, segments);
|
||||
this->do_rebase<MACHO_T>(type, segment_index, segment_offset);
|
||||
segment_offset += sizeof(pint_t);
|
||||
|
||||
if (current_segmment == nullptr or segment_offset > current_segmment->file_size()) {
|
||||
@@ -826,7 +805,7 @@ void BinaryParser::parse_dyldinfo_rebases() {
|
||||
LIEF_WARN("REBASE_OPCODE_DO_REBASE_ULEB_TIMES: Bad offset (0x{:x} > 0x{:x})",
|
||||
segment_offset, current_segmment->file_size());
|
||||
}
|
||||
this->do_rebase<MACHO_T>(type, segment_index, segment_offset, segments);
|
||||
this->do_rebase<MACHO_T>(type, segment_index, segment_offset);
|
||||
segment_offset += sizeof(pint_t);
|
||||
}
|
||||
break;
|
||||
@@ -839,7 +818,7 @@ void BinaryParser::parse_dyldinfo_rebases() {
|
||||
LIEF_WARN("REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: Bad offset (0x{:x} > 0x{:x})",
|
||||
segment_offset, current_segmment->file_size());
|
||||
}
|
||||
this->do_rebase<MACHO_T>(type, segment_index, segment_offset, segments);
|
||||
this->do_rebase<MACHO_T>(type, segment_index, segment_offset);
|
||||
|
||||
segment_offset += this->stream_->read_uleb128() + sizeof(pint_t);
|
||||
|
||||
@@ -861,7 +840,7 @@ void BinaryParser::parse_dyldinfo_rebases() {
|
||||
LIEF_WARN("REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: Bad offset (0x{:x} > 0x{:x})",
|
||||
segment_offset, current_segmment->file_size());
|
||||
}
|
||||
this->do_rebase<MACHO_T>(type, segment_index, segment_offset, segments);
|
||||
this->do_rebase<MACHO_T>(type, segment_index, segment_offset);
|
||||
segment_offset += skip + sizeof(pint_t);
|
||||
}
|
||||
|
||||
@@ -875,6 +854,16 @@ void BinaryParser::parse_dyldinfo_rebases() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tie symbols and relocations
|
||||
for (Relocation& relocation : this->binary_->relocations()) {
|
||||
|
||||
if (not this->binary_->is_valid_addr(relocation.address())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -943,15 +932,11 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
|
||||
bool is_weak_import = false;
|
||||
bool done = false;
|
||||
|
||||
size_t ordinal_table_size = 0;
|
||||
bool use_threaded_rebase_bind = false;
|
||||
uint8_t symbol_flags = 0;
|
||||
std::vector<ThreadedBindData> ordinal_table;
|
||||
|
||||
it_segments segments = this->binary_->segments();
|
||||
this->stream_->setpos(offset);
|
||||
while (not done and this->stream_->pos() < end_offset) {
|
||||
uint8_t imm = this->stream_->peek<uint8_t>() & BIND_IMMEDIATE_MASK;
|
||||
uint8_t imm = this->stream_->peek<uint8_t>() & BIND_IMMEDIATE_MASK;
|
||||
BIND_OPCODES opcode = static_cast<BIND_OPCODES>(this->stream_->read<uint8_t>() & BIND_OPCODE_MASK);
|
||||
|
||||
switch (opcode) {
|
||||
@@ -990,7 +975,6 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
|
||||
case BIND_OPCODES::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
|
||||
{
|
||||
symbol_name = this->stream_->read_string();
|
||||
symbol_flags = imm;
|
||||
|
||||
if ((imm & BIND_SYMBOL_FLAGS_WEAK_IMPORT) != 0) {
|
||||
is_weak_import = true;
|
||||
@@ -1016,6 +1000,7 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
|
||||
{
|
||||
segment_idx = imm;
|
||||
segment_offset = this->stream_->read_uleb128();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1027,22 +1012,18 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
|
||||
|
||||
case BIND_OPCODES::BIND_OPCODE_DO_BIND:
|
||||
{
|
||||
if (not use_threaded_rebase_bind) {
|
||||
this->do_bind<MACHO_T>(
|
||||
BINDING_CLASS::BIND_CLASS_STANDARD,
|
||||
type,
|
||||
segment_idx,
|
||||
segment_offset,
|
||||
symbol_name,
|
||||
library_ordinal,
|
||||
addend,
|
||||
is_weak_import,
|
||||
false,
|
||||
segments);
|
||||
segment_offset += sizeof(pint_t);
|
||||
} else {
|
||||
ordinal_table.push_back(ThreadedBindData{symbol_name, addend, library_ordinal, symbol_flags, type});
|
||||
}
|
||||
this->do_bind<MACHO_T>(
|
||||
BINDING_CLASS::BIND_CLASS_STANDARD,
|
||||
type,
|
||||
segment_idx,
|
||||
segment_offset,
|
||||
symbol_name,
|
||||
library_ordinal,
|
||||
addend,
|
||||
is_weak_import,
|
||||
false,
|
||||
segments);
|
||||
segment_offset += sizeof(pint_t);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1082,8 +1063,12 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
|
||||
|
||||
case BIND_OPCODES::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
|
||||
{
|
||||
count = this->stream_->read_uleb128();
|
||||
skip = this->stream_->read_uleb128();
|
||||
|
||||
// Count
|
||||
count = this->stream_->read_uleb128();
|
||||
|
||||
// Skip
|
||||
skip = this->stream_->read_uleb128();
|
||||
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
this->do_bind<MACHO_T>(
|
||||
@@ -1101,74 +1086,7 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BIND_OPCODES::BIND_OPCODE_THREADED:
|
||||
{
|
||||
const auto subopcode = static_cast<BIND_SUBOPCODE_THREADED>(imm);
|
||||
switch (subopcode) {
|
||||
case BIND_SUBOPCODE_THREADED::BIND_SUBOPCODE_THREADED_APPLY:
|
||||
{
|
||||
uint64_t delta = 0;
|
||||
const SegmentCommand& current_segment = segments[segment_idx];
|
||||
do {
|
||||
const uint64_t address = current_segment.virtual_address() + segment_offset;
|
||||
const std::vector<uint8_t>& content = current_segment.content();
|
||||
if (segment_offset >= content.size() or segment_offset + sizeof(uint64_t) >= content.size()) {
|
||||
LIEF_WARN("Bad segment offset (0x{:x})", segment_offset);
|
||||
delta = 0; // exit from de do ... while
|
||||
break;
|
||||
}
|
||||
auto value = *reinterpret_cast<const uint64_t*>(content.data() + segment_offset);
|
||||
bool is_rebase = (value & (static_cast<uint64_t>(1) << 62)) == 0;
|
||||
|
||||
if (is_rebase) {
|
||||
//LIEF_WARN("do rebase for addr: 0x{:x} vs 0x{:x}", address, current_segment)
|
||||
this->do_rebase<MACHO_T>(static_cast<uint8_t>(REBASE_TYPES::REBASE_TYPE_POINTER),
|
||||
segment_idx, segment_offset, segments);
|
||||
} else {
|
||||
uint16_t ordinal = value & 0xFFFF;
|
||||
if (ordinal >= ordinal_table_size or ordinal >= ordinal_table.size()) {
|
||||
LIEF_WARN("bind ordinal ({:d}) is out of range (max={:d}) for disk pointer 0x{:04x} in "
|
||||
"segment '{}' (segment offset: 0x{:04x})", ordinal, ordinal_table_size, value,
|
||||
current_segment.name(), segment_offset);
|
||||
break;
|
||||
}
|
||||
if (address < current_segment.virtual_address() or
|
||||
address >= (current_segment.virtual_address() + current_segment.virtual_size())) {
|
||||
LIEF_WARN("Bad binding address");
|
||||
break;
|
||||
}
|
||||
const ThreadedBindData& th_bind_data = ordinal_table[ordinal];
|
||||
this->do_bind<MACHO_T>(
|
||||
BINDING_CLASS::BIND_CLASS_THREADED,
|
||||
th_bind_data.type,
|
||||
segment_idx,
|
||||
segment_offset,
|
||||
th_bind_data.symbol_name,
|
||||
th_bind_data.library_ordinal,
|
||||
th_bind_data.addend,
|
||||
th_bind_data.symbol_flags & BIND_SYMBOL_FLAGS_WEAK_IMPORT,
|
||||
false,
|
||||
segments);
|
||||
}
|
||||
// The delta is bits [51..61]
|
||||
// And bit 62 is to tell us if we are a rebase (0) or bind (1)
|
||||
value &= ~(1ull << 62);
|
||||
delta = (value & 0x3FF8000000000000) >> 51;
|
||||
segment_offset += delta * sizeof(pint_t);
|
||||
} while (delta != 0);
|
||||
break;
|
||||
}
|
||||
case BIND_SUBOPCODE_THREADED::BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB:
|
||||
{
|
||||
count = this->stream_->read_uleb128();
|
||||
ordinal_table_size = count + 1; // the +1 comes from: 'ld64 wrote the wrong value here and we need to offset by 1 for now.'
|
||||
use_threaded_rebase_bind = true;
|
||||
ordinal_table.reserve(ordinal_table_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
LIEF_ERR("Unsupported opcode: 0x{:x}", static_cast<uint32_t>(opcode));
|
||||
@@ -1176,11 +1094,6 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (use_threaded_rebase_bind) {
|
||||
dyldinfo.binding_encoding_version_ = DyldInfo::BINDING_ENCODING_VERSION::V2;
|
||||
} else {
|
||||
dyldinfo.binding_encoding_version_ = DyldInfo::BINDING_ENCODING_VERSION::V1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1543,16 +1456,12 @@ void BinaryParser::do_bind(BINDING_CLASS cls,
|
||||
binding_info->library_ = &libraries[ord - 1];
|
||||
}
|
||||
|
||||
Symbol* symbol = nullptr;
|
||||
auto search = this->memoized_symbols_.find(symbol_name);
|
||||
if (search != this->memoized_symbols_.end()) {
|
||||
symbol = search->second;
|
||||
} else {
|
||||
symbol = this->binary_->get_symbol(symbol_name);
|
||||
}
|
||||
if (symbol != nullptr) {
|
||||
binding_info->symbol_ = symbol;
|
||||
symbol->binding_info_ = binding_info.get();
|
||||
|
||||
if (this->binary_->has_symbol(symbol_name)) {
|
||||
Symbol& symbol = this->binary_->get_symbol(symbol_name);
|
||||
//symbol.value(address);
|
||||
binding_info->symbol_ = &symbol;
|
||||
symbol.binding_info_ = binding_info.get();
|
||||
} else {
|
||||
LIEF_ERR("New symbol found: {}", symbol_name);
|
||||
}
|
||||
@@ -1563,10 +1472,11 @@ void BinaryParser::do_bind(BINDING_CLASS cls,
|
||||
}
|
||||
|
||||
template<class MACHO_T>
|
||||
void BinaryParser::do_rebase(uint8_t type, uint8_t segment_idx, uint64_t segment_offset,
|
||||
const it_segments& segments) {
|
||||
void BinaryParser::do_rebase(uint8_t type, uint8_t segment_idx, uint64_t segment_offset) {
|
||||
using pint_t = typename MACHO_T::uint;
|
||||
|
||||
it_segments segments = this->binary_->segments();
|
||||
|
||||
if (segment_idx >= segments.size()) {
|
||||
LIEF_ERR("Wrong index ({:d})", segment_idx);
|
||||
return;
|
||||
@@ -1582,7 +1492,7 @@ void BinaryParser::do_rebase(uint8_t type, uint8_t segment_idx, uint64_t segment
|
||||
|
||||
// Check if a relocation already exists:
|
||||
std::unique_ptr<RelocationDyld> new_relocation{new RelocationDyld{address, type}};
|
||||
auto result = segment.relocations_.emplace(new_relocation.get());
|
||||
auto&& result = segment.relocations_.emplace(new_relocation.get());
|
||||
Relocation* reloc = *result.first;
|
||||
|
||||
// result.second is true if the insertion succeed
|
||||
@@ -1602,9 +1512,15 @@ void BinaryParser::do_rebase(uint8_t type, uint8_t segment_idx, uint64_t segment
|
||||
reloc->section_ = section;
|
||||
|
||||
// Tie symbol
|
||||
const auto it_symbol = this->memoized_symbols_by_address_.find(address);
|
||||
if (it_symbol != this->memoized_symbols_by_address_.end()) {
|
||||
reloc->symbol_ = it_symbol->second;
|
||||
auto&& it_symbol = std::find_if(
|
||||
std::begin(this->binary_->symbols_),
|
||||
std::end(this->binary_->symbols_),
|
||||
[address] (const Symbol* sym) {
|
||||
return sym->value() == address;
|
||||
});
|
||||
|
||||
if (it_symbol != std::end(this->binary_->symbols_)) {
|
||||
reloc->symbol_ = *it_symbol;
|
||||
}
|
||||
|
||||
switch (static_cast<REBASE_TYPES>(type)) {
|
||||
@@ -1621,11 +1537,6 @@ void BinaryParser::do_rebase(uint8_t type, uint8_t segment_idx, uint64_t segment
|
||||
reloc->size_ = sizeof(uint32_t) * 8;
|
||||
break;
|
||||
}
|
||||
case REBASE_TYPES::REBASE_TYPE_THREADED:
|
||||
{
|
||||
reloc->size_ = sizeof(pint_t) * 8;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
|
||||
+10
-6
@@ -288,8 +288,9 @@ void Builder::build_load_commands(void) {
|
||||
}
|
||||
|
||||
void Builder::build_uuid(void) {
|
||||
const auto uuid_it = std::find_if(
|
||||
std::begin(this->binary_->commands_), std::end(this->binary_->commands_),
|
||||
auto&& uuid_it = std::find_if(
|
||||
std::begin(this->binary_->commands_),
|
||||
std::end(this->binary_->commands_),
|
||||
[] (const LoadCommand* command) {
|
||||
return (typeid(*command) == typeid(UUIDCommand));
|
||||
});
|
||||
@@ -298,10 +299,11 @@ void Builder::build_uuid(void) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* uuid_cmd = reinterpret_cast<UUIDCommand*>(*uuid_it);
|
||||
UUIDCommand* uuid_cmd = dynamic_cast<UUIDCommand*>(*uuid_it);
|
||||
uuid_command raw_cmd;
|
||||
std::fill(
|
||||
reinterpret_cast<uint8_t*>(&raw_cmd), reinterpret_cast<uint8_t*>(&raw_cmd) + sizeof(uuid_command),
|
||||
reinterpret_cast<uint8_t*>(&raw_cmd),
|
||||
reinterpret_cast<uint8_t*>(&raw_cmd) + sizeof(uuid_command),
|
||||
0);
|
||||
|
||||
raw_cmd.cmd = static_cast<uint32_t>(uuid_cmd->command());
|
||||
@@ -316,7 +318,8 @@ void Builder::build_uuid(void) {
|
||||
}
|
||||
|
||||
std::copy(
|
||||
reinterpret_cast<const uint8_t*>(&raw_cmd), reinterpret_cast<const uint8_t*>(&raw_cmd) + sizeof(uuid_command),
|
||||
reinterpret_cast<uint8_t*>(&raw_cmd),
|
||||
reinterpret_cast<uint8_t*>(&raw_cmd) + sizeof(uuid_command),
|
||||
uuid_cmd->originalData_.data());
|
||||
}
|
||||
|
||||
@@ -343,7 +346,8 @@ void Builder::write(const std::string& filename) const {
|
||||
this->raw_.get(content);
|
||||
|
||||
std::copy(
|
||||
std::begin(content), std::end(content),
|
||||
std::begin(content),
|
||||
std::end(content),
|
||||
std::ostreambuf_iterator<char>(output_file));
|
||||
} else {
|
||||
LIEF_ERR("Fail to write binary file");
|
||||
|
||||
+178
-162
@@ -55,17 +55,12 @@ void Builder::build_segments(void) {
|
||||
for (SegmentCommand& segment : binary->segments()) {
|
||||
LIEF_DEBUG("{}", segment);
|
||||
segment_t segment_header;
|
||||
std::memset(&segment_header, 0, sizeof(segment_header));
|
||||
|
||||
segment_header.cmd = static_cast<uint32_t>(segment.command());
|
||||
segment_header.cmdsize = static_cast<uint32_t>(segment.size());
|
||||
|
||||
const std::string& seg_name = segment.name();
|
||||
const uint32_t segname_length = std::min<uint32_t>(seg_name.size() + 1,
|
||||
sizeof(segment_header.segname));
|
||||
std::copy(seg_name.c_str(), seg_name.c_str() + segname_length,
|
||||
std::begin(segment_header.segname));
|
||||
|
||||
std::copy(
|
||||
seg_name.c_str(), seg_name.c_str() + sizeof(segment_header.segname),
|
||||
segment_header.segname);
|
||||
segment_header.vmaddr = static_cast<uint__>(segment.virtual_address());
|
||||
segment_header.vmsize = static_cast<uint__>(segment.virtual_size());
|
||||
segment_header.fileoff = static_cast<uint__>(segment.file_offset());
|
||||
@@ -80,7 +75,10 @@ void Builder::build_segments(void) {
|
||||
if (content.size() != segment.file_size()) {
|
||||
throw LIEF::builder_error("content.size() != segment.file_size()");
|
||||
}
|
||||
//this->raw_.seekp(segment.file_offset());
|
||||
//this->raw_.write(content);
|
||||
|
||||
//const size_t original_size = segment.originalData_.size();
|
||||
segment.originalData_.clear();
|
||||
|
||||
std::move(
|
||||
@@ -104,17 +102,13 @@ void Builder::build_segments(void) {
|
||||
const std::string& segment_name = segment.name();
|
||||
LIEF_DEBUG("{}", section);
|
||||
section_t header;
|
||||
std::memset(&header, 0, sizeof(header));
|
||||
std::copy(
|
||||
sec_name.c_str(), sec_name.c_str() + sizeof(header.sectname),
|
||||
header.sectname);
|
||||
|
||||
const uint32_t segname_length = std::min<uint32_t>(segment_name.size() + 1,
|
||||
sizeof(header.segname));
|
||||
std::copy(segment_name.c_str(), segment_name.c_str() + segname_length,
|
||||
std::begin(header.segname));
|
||||
|
||||
const uint32_t secname_length = std::min<uint32_t>(sec_name.size() + 1,
|
||||
sizeof(header.sectname));
|
||||
std::copy(sec_name.c_str(), sec_name.c_str() + secname_length,
|
||||
std::begin(header.sectname));
|
||||
std::copy(
|
||||
segment_name.c_str(), segment_name.c_str() + sizeof(header.segname),
|
||||
header.segname);
|
||||
|
||||
header.addr = static_cast<uint__>(section.address());
|
||||
header.size = static_cast<uint__>(section.size());
|
||||
@@ -140,6 +134,74 @@ void Builder::build_segments(void) {
|
||||
} // build_segment
|
||||
|
||||
|
||||
template<typename T>
|
||||
void Builder::build_symbols(void) {
|
||||
#if 0
|
||||
using nlist_t = typename T::nlist;
|
||||
|
||||
auto itSymbolCommand = std::find_if(
|
||||
std::begin(this->binary_->commands_),
|
||||
std::end(this->binary_->commands_),
|
||||
[] (const LoadCommand* command) {
|
||||
return command->command() == LOAD_COMMAND_TYPES::LC_SYMTAB;
|
||||
});
|
||||
if (itSymbolCommand == std::end(this->binary_->commands_)) {
|
||||
VLOG(VDEBUG) << "[-] No symbols" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
VLOG(VDEBUG) << "[+] Building symbols" << std::endl;
|
||||
const SymbolCommand* symbol_command = static_cast<const SymbolCommand*>(*itSymbolCommand);
|
||||
symtab_command command;
|
||||
|
||||
command.cmd = static_cast<uint32_t>(symbol_command->command());
|
||||
command.cmdsize = static_cast<uint32_t>(symbol_command->size());
|
||||
command.symoff = static_cast<uint32_t>(symbol_command->symbol_offset());
|
||||
command.nsyms = static_cast<uint32_t>(symbol_command->numberof_symbols());
|
||||
command.stroff = static_cast<uint32_t>(symbol_command->strings_offset());
|
||||
|
||||
|
||||
|
||||
command.strsize = static_cast<uint32_t>(symbol_command->strings_size() + delta);
|
||||
|
||||
uint64_t loadCommandsOffset = symbol_command->command_offset();
|
||||
|
||||
this->raw_.seekp(loadCommandsOffset);
|
||||
this->raw_.write(reinterpret_cast<uint8_t*>(&command), sizeof(symtab_command));
|
||||
|
||||
uint32_t string_idx = 1;
|
||||
for (size_t i = 0; i < this->binary_->symbols_.size(); ++i) {
|
||||
nlist_t symbol;
|
||||
const auto& binary_symbol = this->binary_->symbols_[i];
|
||||
if (not binary_symbol->name().empty()) {
|
||||
const std::string& name = binary_symbol->name();
|
||||
const uint32_t name_offset = symbol_command->strings_offset() + string_idx;
|
||||
|
||||
|
||||
this->raw_.seekp(name_offset);
|
||||
this->raw_.write(reinterpret_cast<const uint8_t*>(name.data()), name.size() + 1);
|
||||
|
||||
symbol.n_strx = string_idx;
|
||||
string_idx += name.size() + 1;
|
||||
}
|
||||
|
||||
symbol.n_type = static_cast<uint8_t>(binary_symbol->type());
|
||||
symbol.n_sect = static_cast<uint8_t>(binary_symbol->numberof_sections());
|
||||
if (std::is_same<T, MachO32>::value) {
|
||||
symbol.n_desc = static_cast<uint16_t>(binary_symbol->description());
|
||||
} else {
|
||||
symbol.n_desc = static_cast<int16_t>(binary_symbol->description());
|
||||
}
|
||||
symbol.n_value = static_cast<uint32_t>(binary_symbol->value());
|
||||
const uint32_t offset = static_cast<uint32_t>(symbol_command->symbol_offset() + i * sizeof(nlist_t));
|
||||
|
||||
this->raw_.seekp(offset);
|
||||
this->raw_.write(reinterpret_cast<const uint8_t*>(&symbol), sizeof(nlist_t));
|
||||
}
|
||||
#endif
|
||||
} // build_symbols
|
||||
|
||||
|
||||
template<typename T>
|
||||
void Builder::build(DylibCommand* library) {
|
||||
LIEF_DEBUG("Build Dylib '{}'", library->name());
|
||||
@@ -330,10 +392,6 @@ template<class T>
|
||||
void Builder::build(DyldInfo* dyld_info) {
|
||||
LIEF_DEBUG("Build '{}'", to_string(dyld_info->command()));
|
||||
|
||||
// /!\ Force to update relocation cache that is used by the following functions
|
||||
// TODO(romain): This looks like a hack
|
||||
this->binary_->relocations();
|
||||
|
||||
dyld_info->update_export_trie().update_rebase_info().update_binding_info();
|
||||
|
||||
const uint32_t raw_size = sizeof(dyld_info_command);
|
||||
@@ -359,7 +417,8 @@ void Builder::build(DyldInfo* dyld_info) {
|
||||
dyld_info->size_ = sizeof(dyld_info_command);
|
||||
dyld_info->originalData_.clear();
|
||||
std::move(
|
||||
reinterpret_cast<uint8_t*>(&raw_cmd), reinterpret_cast<uint8_t*>(&raw_cmd) + sizeof(dyld_info_command),
|
||||
reinterpret_cast<uint8_t*>(&raw_cmd),
|
||||
reinterpret_cast<uint8_t*>(&raw_cmd) + sizeof(dyld_info_command),
|
||||
std::back_inserter(dyld_info->originalData_));
|
||||
dyld_info->originalData_.insert(std::end(dyld_info->originalData_), padding, 0);
|
||||
|
||||
@@ -384,7 +443,8 @@ void Builder::build(DyldInfo* dyld_info) {
|
||||
std::vector<uint8_t> content = rebase_segment->content();
|
||||
|
||||
std::move(
|
||||
std::begin(rebase_opcodes), std::end(rebase_opcodes),
|
||||
std::begin(rebase_opcodes),
|
||||
std::end(rebase_opcodes),
|
||||
content.data() + relative_offset);
|
||||
rebase_segment->content(std::move(content));
|
||||
}
|
||||
@@ -406,7 +466,8 @@ void Builder::build(DyldInfo* dyld_info) {
|
||||
uint64_t relative_offset = raw_cmd.bind_off - bind_segment->file_offset();
|
||||
std::vector<uint8_t> content = bind_segment->content();
|
||||
std::move(
|
||||
std::begin(bind_opcodes), std::end(bind_opcodes),
|
||||
std::begin(bind_opcodes),
|
||||
std::end(bind_opcodes),
|
||||
content.data() + relative_offset);
|
||||
bind_segment->content(std::move(content));
|
||||
}
|
||||
@@ -429,7 +490,8 @@ void Builder::build(DyldInfo* dyld_info) {
|
||||
uint64_t relative_offset = raw_cmd.weak_bind_off - weak_bind_segment->file_offset();
|
||||
std::vector<uint8_t> content = weak_bind_segment->content();
|
||||
std::move(
|
||||
std::begin(weak_bind_opcodes), std::end(weak_bind_opcodes),
|
||||
std::begin(weak_bind_opcodes),
|
||||
std::end(weak_bind_opcodes),
|
||||
content.data() + relative_offset);
|
||||
weak_bind_segment->content(std::move(content));
|
||||
}
|
||||
@@ -452,7 +514,8 @@ void Builder::build(DyldInfo* dyld_info) {
|
||||
uint64_t relative_offset = raw_cmd.lazy_bind_off - lazy_bind_segment->file_offset();
|
||||
std::vector<uint8_t> content = lazy_bind_segment->content();
|
||||
std::move(
|
||||
std::begin(lazy_bind_opcodes), std::end(lazy_bind_opcodes),
|
||||
std::begin(lazy_bind_opcodes),
|
||||
std::end(lazy_bind_opcodes),
|
||||
content.data() + relative_offset);
|
||||
lazy_bind_segment->content(std::move(content));
|
||||
}
|
||||
@@ -474,7 +537,8 @@ void Builder::build(DyldInfo* dyld_info) {
|
||||
uint64_t relative_offset = raw_cmd.export_off - export_segment->file_offset();
|
||||
std::vector<uint8_t> content = export_segment->content();
|
||||
std::move(
|
||||
std::begin(export_trie), std::end(export_trie),
|
||||
std::begin(export_trie),
|
||||
std::end(export_trie),
|
||||
content.data() + relative_offset);
|
||||
export_segment->content(std::move(content));
|
||||
}
|
||||
@@ -499,7 +563,8 @@ void Builder::build(FunctionStarts* function_starts) {
|
||||
std::vector<uint8_t> encoded = LEB128::uencode(delta);
|
||||
|
||||
std::move(
|
||||
std::begin(encoded), std::end(encoded),
|
||||
std::begin(encoded),
|
||||
std::end(encoded),
|
||||
std::back_inserter(packed_functions));
|
||||
prev_address = address;
|
||||
}
|
||||
@@ -517,7 +582,8 @@ void Builder::build(FunctionStarts* function_starts) {
|
||||
std::vector<uint8_t> content = segment->content();
|
||||
uint64_t relative_offset = function_starts->data_offset() - segment->file_offset();
|
||||
std::move(
|
||||
std::begin(packed_functions), std::end(packed_functions),
|
||||
std::begin(packed_functions),
|
||||
std::end(packed_functions),
|
||||
content.data() + relative_offset);
|
||||
segment->content(std::move(content));
|
||||
|
||||
@@ -549,125 +615,32 @@ void Builder::build(FunctionStarts* function_starts) {
|
||||
function_starts->originalData_.insert(std::end(function_starts->originalData_), struct_padding, 0);
|
||||
}
|
||||
|
||||
template<typename T, typename HANDLER>
|
||||
std::vector<std::string> Builder::optimize(const HANDLER& container,
|
||||
std::function<std::string(const typename HANDLER::value_type)> getter,
|
||||
std::unordered_map<std::string, size_t> *of_map_p) {
|
||||
// TODO(romain): This function is also used in the ELF's builder -> move it in the 'utils' part
|
||||
|
||||
std::set<std::string> string_table;
|
||||
std::vector<std::string> string_table_optimized;
|
||||
string_table_optimized.reserve(container.size());
|
||||
|
||||
// reverse all symbol names and sort them so we can merge then in the linear time:
|
||||
// aaa, aadd, aaaa, cca, ca -> aaaa, aaa, acc, ac ddaa
|
||||
std::transform(
|
||||
std::begin(container), std::end(container),
|
||||
std::inserter(string_table, std::end(string_table)),
|
||||
getter);
|
||||
|
||||
for (auto &val: string_table) {
|
||||
string_table_optimized.emplace_back(std::move(val));
|
||||
std::reverse(std::begin(string_table_optimized.back()), std::end(string_table_optimized.back()));
|
||||
}
|
||||
|
||||
std::sort(std::begin(string_table_optimized), std::end(string_table_optimized),
|
||||
[] (const std::string& lhs, const std::string& rhs) {
|
||||
bool ret = false;
|
||||
if (lhs.size() > rhs.size()) {
|
||||
auto res = lhs.compare(0, rhs.size(), rhs);
|
||||
ret = (res <= 0);
|
||||
} else {
|
||||
auto res = rhs.compare(0, lhs.size(), lhs);
|
||||
ret = (res > 0);
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
|
||||
// as all elements that can be merged are adjacent we can just go through the list once
|
||||
// and memorize one we merged to calculate the offsets later
|
||||
std::unordered_map<std::string, std::string> merged_map;
|
||||
size_t to_set_idx = 0, cur_elm_idx = 1;
|
||||
for (; cur_elm_idx < string_table_optimized.size(); ++cur_elm_idx) {
|
||||
auto &cur_elm = string_table_optimized[cur_elm_idx];
|
||||
auto &to_set_elm = string_table_optimized[to_set_idx];
|
||||
if (to_set_elm.size() >= cur_elm.size()) {
|
||||
auto ret = to_set_elm.compare(0, cur_elm.size(), cur_elm);
|
||||
if (ret == 0) {
|
||||
// when memorizing reverse back symbol names
|
||||
std::string rev_cur_elm = cur_elm;
|
||||
std::string rev_to_set_elm = to_set_elm;
|
||||
std::reverse(std::begin(rev_cur_elm), std::end(rev_cur_elm));
|
||||
std::reverse(std::begin(rev_to_set_elm), std::end(rev_to_set_elm));
|
||||
merged_map[rev_cur_elm] = rev_to_set_elm;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
++to_set_idx;
|
||||
std::swap(string_table_optimized[to_set_idx], cur_elm);
|
||||
}
|
||||
// if the first one is empty
|
||||
if (string_table_optimized[0].size() == 0) {
|
||||
std::swap(string_table_optimized[0], string_table_optimized[to_set_idx]);
|
||||
--to_set_idx;
|
||||
}
|
||||
string_table_optimized.resize(to_set_idx + 1);
|
||||
|
||||
//reverse symbols back and sort them again
|
||||
for (auto &val: string_table_optimized) {
|
||||
std::reverse(std::begin(val), std::end(val));
|
||||
}
|
||||
std::sort(std::begin(string_table_optimized), std::end(string_table_optimized));
|
||||
|
||||
if (of_map_p) {
|
||||
std::unordered_map<std::string, size_t> offset_map;
|
||||
offset_map[""] = 0;
|
||||
size_t offset_counter = 1;
|
||||
for (const auto &v : string_table_optimized) {
|
||||
offset_map[v] = offset_counter;
|
||||
offset_counter += v.size() + 1;
|
||||
}
|
||||
for (const auto &kv : merged_map) {
|
||||
offset_map[kv.first] = offset_map[kv.second] + (kv.second.size() - kv.first.size());
|
||||
}
|
||||
*of_map_p = std::move(offset_map);
|
||||
}
|
||||
|
||||
return string_table_optimized;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class T>
|
||||
void Builder::build(SymbolCommand* symbol_command) {
|
||||
|
||||
//template <typename A>
|
||||
//void SymbolTableAtom<A>::encode()
|
||||
//{
|
||||
// // Note: We lay out the symbol table so that the strings for the stabs (local) symbols are at the
|
||||
// // end of the string pool. The stabs strings are not used when calculated the UUID for the image.
|
||||
// // If the stabs strings were not last, the string offsets for all other symbols may very which would alter the UUID.
|
||||
//
|
||||
// // reserve space for local symbols
|
||||
// +---------------------+
|
||||
// | |
|
||||
// | symtab_command |
|
||||
// | |
|
||||
// +---------------------+
|
||||
// | |
|
||||
// | n_list |
|
||||
// | |
|
||||
// +---------------------+
|
||||
// | |
|
||||
// | string table |
|
||||
// | |
|
||||
// +---------------------+
|
||||
// +---------------------+
|
||||
// | |
|
||||
// | symtab_command |
|
||||
// | |
|
||||
// +---------------------+
|
||||
// | |
|
||||
// | n_list |
|
||||
// | |
|
||||
// +---------------------+
|
||||
// | |
|
||||
// | string table |
|
||||
// | |
|
||||
// +---------------------+
|
||||
|
||||
using nlist_t = typename T::nlist;
|
||||
using uint = typename T::uint;
|
||||
|
||||
symtab_command symtab;
|
||||
|
||||
auto cmp_string = [] (const std::string& a, const std::string& b) {
|
||||
return (a.size() >= b.size() and a != b);
|
||||
};
|
||||
|
||||
std::vector<Symbol*> symbols;
|
||||
symbols.reserve(this->binary_->symbols().size());
|
||||
@@ -675,70 +648,107 @@ void Builder::build(SymbolCommand* symbol_command) {
|
||||
|
||||
// 1. Fill the string table
|
||||
// -------------------------------------
|
||||
std::set<std::string, decltype(cmp_string)> string_table{cmp_string};
|
||||
std::vector<std::string> string_table_opt;
|
||||
for (Symbol& s : this->binary_->symbols()) {
|
||||
if (s.origin() == SYMBOL_ORIGINS::SYM_ORIGIN_LC_SYMTAB) {
|
||||
string_table.insert(s.name());
|
||||
symbols.push_back(&s);
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, size_t> offset_name_map;
|
||||
std::vector<std::string> string_table_opt = optimize<Symbol, decltype(symbols)>(
|
||||
symbols, [] (const Symbol* sym) { return sym->name(); },
|
||||
&offset_name_map);
|
||||
std::copy_if(
|
||||
std::begin(string_table),
|
||||
std::end(string_table),
|
||||
std::back_inserter(string_table_opt),
|
||||
[&string_table_opt] (const std::string& name) {
|
||||
|
||||
auto&& it = std::find_if(
|
||||
std::begin(string_table_opt),
|
||||
std::end(string_table_opt),
|
||||
[&name] (const std::string& nameopt) {
|
||||
return nameopt.substr(nameopt.size() - name.size()) == name ;
|
||||
});
|
||||
|
||||
return (it == std::end(string_table_opt));
|
||||
});
|
||||
|
||||
std::vector<uint8_t> raw_symbol_names;
|
||||
|
||||
// 0 index is reserved
|
||||
vector_iostream raw_symbol_names;
|
||||
raw_symbol_names.write<uint8_t>(0);
|
||||
for (std::string name : string_table_opt) {
|
||||
raw_symbol_names.write(name);
|
||||
raw_symbol_names.push_back(0);
|
||||
for (const std::string& name : string_table_opt) {
|
||||
std::move(
|
||||
std::begin(name), std::end(name),
|
||||
std::back_inserter(raw_symbol_names));
|
||||
raw_symbol_names.push_back(0);
|
||||
}
|
||||
|
||||
// If the table is smaller than th original one, fill with 0
|
||||
if (raw_symbol_names.size() < symbol_command->strings_size()) {
|
||||
const size_t padding = symbol_command->strings_size() - raw_symbol_names.size();
|
||||
raw_symbol_names.write(padding, 0);
|
||||
raw_symbol_names.insert(
|
||||
std::end(raw_symbol_names),
|
||||
symbol_command->strings_size() - raw_symbol_names.size() ,
|
||||
0
|
||||
);
|
||||
}
|
||||
raw_symbol_names.align(sizeof(uint));
|
||||
|
||||
size_t padding = align(raw_symbol_names.size(), sizeof(uint)) - raw_symbol_names.size();
|
||||
raw_symbol_names.insert(std::end(raw_symbol_names), padding, 0);
|
||||
|
||||
|
||||
// To be removed later
|
||||
if (raw_symbol_names.size() > symbol_command->strings_size()) {
|
||||
LIEF_WARN("Larger symbol names size is not supported yet");
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the segment that contains the string table
|
||||
// Update the segment handling
|
||||
// the string table
|
||||
SegmentCommand* segment = this->binary_->segment_from_offset(symbol_command->strings_offset());
|
||||
if (segment == nullptr) {
|
||||
LIEF_WARN("Can't find segment associated with string table");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> symname_data = raw_symbol_names.raw();
|
||||
std::vector<uint8_t> content = segment->content();
|
||||
uint64_t relative_offset = symbol_command->strings_offset() - segment->file_offset();
|
||||
std::move(std::begin(symname_data), std::end(symname_data), content.data() + relative_offset);
|
||||
std::move(
|
||||
std::begin(raw_symbol_names),
|
||||
std::end(raw_symbol_names),
|
||||
content.data() + relative_offset);
|
||||
segment->content(std::move(content));
|
||||
|
||||
// 2. Fill the n_list table
|
||||
// -------------------------------------
|
||||
vector_iostream nlist_table;
|
||||
std::vector<uint8_t> nlist_table;
|
||||
nlist_table.reserve(symbols.size() * sizeof(nlist_t));
|
||||
for (Symbol* sym : symbols) {
|
||||
const std::string& name = sym->name();
|
||||
const auto it_name = offset_name_map.find(name);
|
||||
auto&& it_name = std::search(
|
||||
std::begin(raw_symbol_names),
|
||||
std::end(raw_symbol_names),
|
||||
name.c_str(),
|
||||
name.c_str() + name.size() + 1);
|
||||
|
||||
if (it_name == std::end(offset_name_map)) {
|
||||
if (it_name == std::end(raw_symbol_names)) {
|
||||
LIEF_WARN("Can't find name offset for symbol {}", sym->name());
|
||||
continue;
|
||||
}
|
||||
const size_t name_offset = std::distance(std::begin(raw_symbol_names), it_name);
|
||||
|
||||
nlist_t nl;
|
||||
nl.n_strx = static_cast<uint32_t>(it_name->second);
|
||||
nl.n_strx = static_cast<uint32_t>(name_offset);
|
||||
nl.n_type = static_cast<uint8_t>(sym->type());
|
||||
nl.n_sect = static_cast<uint32_t>(sym->numberof_sections());
|
||||
nl.n_desc = static_cast<uint16_t>(sym->description());
|
||||
nl.n_value = static_cast<uint>(sym->value());
|
||||
|
||||
nlist_table.write(nl);
|
||||
nlist_table.insert(
|
||||
std::end(nlist_table),
|
||||
reinterpret_cast<const uint8_t*>(&nl),
|
||||
reinterpret_cast<const uint8_t*>(&nl) + sizeof(nlist_t)
|
||||
);
|
||||
}
|
||||
|
||||
if (nlist_table.size() != symbol_command->numberof_symbols() * sizeof(nlist_t)) {
|
||||
@@ -754,14 +764,19 @@ void Builder::build(SymbolCommand* symbol_command) {
|
||||
|
||||
content = segment->content();
|
||||
relative_offset = symbol_command->symbol_offset() - segment->file_offset();
|
||||
std::vector<uint8_t> raw_nlist_table = nlist_table.raw();
|
||||
std::move(std::begin(raw_nlist_table), std::end(raw_nlist_table),
|
||||
content.data() + relative_offset);
|
||||
std::move(
|
||||
std::begin(nlist_table),
|
||||
std::end(nlist_table),
|
||||
content.data() + relative_offset);
|
||||
segment->content(std::move(content));
|
||||
|
||||
// 3. Fill the Header
|
||||
std::memset(&symtab, 0, sizeof(symtab_command));
|
||||
std::fill(
|
||||
reinterpret_cast<uint8_t*>(&symtab),
|
||||
reinterpret_cast<uint8_t*>(&symtab) + sizeof(symtab_command),
|
||||
0);
|
||||
|
||||
//const uint32_t size_needed = sizeof(symtab_command) + nlist_table.size() + raw_symbol_names.size();
|
||||
symtab.cmd = static_cast<uint32_t>(symbol_command->command());
|
||||
symtab.cmdsize = static_cast<uint32_t>(symbol_command->size());
|
||||
symtab.symoff = static_cast<uint32_t>(symbol_command->symbol_offset()); // **Usually** After the header
|
||||
@@ -774,6 +789,7 @@ void Builder::build(SymbolCommand* symbol_command) {
|
||||
SegmentCommand& linkedit = *this->binary_->get_segment("__LINKEDIT");
|
||||
size_t delta = linkedit.file_offset() + linkedit.file_size();
|
||||
delta = delta - (symbol_command->strings_offset() + symbol_command->strings_size());
|
||||
//std::cout << std::hex << "delta:" << delta << std::endl;
|
||||
symtab.strsize = static_cast<uint32_t>(symbol_command->strings_size() + delta);
|
||||
|
||||
symbol_command->originalData_.clear();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user