Compare commits

..
Author SHA1 Message Date
Romain Thomas e3ea0d510b Add changelog and bump version 2021-03-02 04:44:06 +01:00
Romain Thomas 91bfa9e952 Add check on the signature size 2021-03-02 04:40:02 +01:00
Romain Thomas 097b35511e Fix error 2021-02-24 08:02:51 +01:00
Romain Thomas 1dd7317a0c Fix error 2021-02-24 07:36:09 +01:00
Romain Thomas 0e12916531 Bump version 2021-02-24 07:04:38 +01:00
Romain Thomas 9fb11539da Resolve #551 2021-02-24 07:01:49 +01:00
Romain Thomas 980ed6b3fb Update changelog 2021-02-22 13:38:24 +01:00
Romain Thomas a6d9ea90a2 Add more information than just BAD_SIGNATURE 2021-02-21 18:03:51 +01:00
Romain Thomas 8d20b9ba65 Resolve #532 2021-02-21 18:02:39 +01:00
Romain Thomas eb24a317fa Fix appveyor tag 2021-02-21 15:38:35 +01:00
Romain Thomas c0fa4a6455 Fix missing env variable 2021-02-21 13:03:37 +01:00
Romain Thomas 3970c4d4e2 update auditwheel command 2021-02-21 13:03:31 +01:00
Romain Thomas 96c7e90231 Fix typo 2021-02-21 13:03:24 +01:00
Romain Thomas badfcf69a7 Update Linux CI 2021-02-21 13:03:10 +01:00
Romain Thomas d45e1946e3 Fix typo 2021-02-21 13:01:41 +01:00
Romain Thomas 62d4fb61ea Fix error on Appveyor 2021-02-21 13:00:40 +01:00
Romain Thomas 0c88cc740f Fix condition 2021-02-21 12:57:45 +01:00
Romain Thomas b2b7783ec0 Fix related to #540 2021-02-21 12:57:14 +01:00
Romain Thomas 9790ddfa82 The last data directory might not be null
See: bc203f2b6a928f1457e9ca99456747bcb7adbbfff789d1c47e9479aac11598af
2021-02-21 12:56:01 +01:00
Romain Thomas 986a30e014 Do not take account sections with empty content 2021-02-21 12:55:54 +01:00
Romain Thomas 03a18cb202 Do not trunc section's name on a null char
If the section's name contains bytes after the null char, they should
be considered while computing the authentihash.
2021-02-21 12:55:38 +01:00
Romain Thomas c37ee0742a Handle content between two sections that is not wrapped by a section 2021-02-21 12:55:24 +01:00
Romain Thomas 2ab604d36f Resolve #548 2021-02-21 12:55:18 +01:00
152 changed files with 17043 additions and 18933 deletions
+23 -16
View File
@@ -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
# ======================
+56 -5
View File
@@ -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>
-2
View File
@@ -17,8 +17,6 @@
#define LIEF_C_TYPES_H_
#include <stdint.h>
#ifndef __cplusplus
#ifndef bool
typedef int bool;
#endif
#endif
#endif
+2 -10
View File
@@ -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"
+7 -8
View File
@@ -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}/"
-1
View File
@@ -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"
-9
View File
@@ -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) "")
-72
View File
@@ -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();
});
}
}
}
-4
View File
@@ -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")
-1
View File
@@ -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);
-1
View File
@@ -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);
-1
View File
@@ -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");
}
+2 -3
View File
@@ -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));
+1 -1
View File
@@ -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)
+2 -2
View File
@@ -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",
-7
View File
@@ -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),
+2 -4
View File
@@ -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 += " | ";
-13
View File
@@ -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")
-35
View File
@@ -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", &current_platform,
"Return the current plaform (Linux, Windows, ...) as a :attr:`lief.PLATFORMS` enum");
}
}
-28
View File
@@ -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
-3
View File
@@ -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);
+198
View File
@@ -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)
+13 -23
View File
@@ -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
View File
@@ -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)
-7
View File
@@ -60,13 +60,6 @@ Class
----------
Field
*****
.. doxygenclass:: LIEF::DEX::Field
:project: lief
----------
Code Info
*********
-12
View File
@@ -51,18 +51,6 @@ Method
----------
Field
*****
.. autoclass:: lief.DEX.Field
:members:
:inherited-members:
:undoc-members:
----------
Class
******
+7 -64
View File
@@ -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
+5 -5
View File
@@ -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::
-19
View File
@@ -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)
+1 -13
View File
@@ -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,
-3
View File
@@ -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 = "");
-9
View File
@@ -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;
-3
View File
@@ -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;
-1
View File
@@ -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
-11
View File
@@ -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_;
-77
View File
@@ -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
-6
View File
@@ -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_;
-12
View File
@@ -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_;
-1
View File
@@ -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;
-1
View File
@@ -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;
-5
View File
@@ -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>;
+1 -7
View File
@@ -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
+1 -6
View File
@@ -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);
-2
View File
@@ -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&);
+2 -4
View File
@@ -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_;
-1
View File
@@ -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 */
};
-1
View File
@@ -230,7 +230,6 @@
#undef EM_NORC
#undef EM_CSR_KALIMBA
#undef EM_AMDGPU
#undef EM_RISCV
#undef EM_BPF
+8 -28
View File
@@ -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;
};
+9 -12
View File
@@ -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_;
};
-10
View File
@@ -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);
+7 -18
View File
@@ -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};
};
}
-1
View File
@@ -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);
+1 -6
View File
@@ -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);
+2 -5
View File
@@ -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_;
};
-5
View File
@@ -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_;
+1 -12
View File
@@ -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) {
+6 -6
View File
@@ -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
-2
View File
@@ -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);
-9
View 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;
+2 -4
View File
@@ -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);
+3 -6
View File
@@ -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_;
-6
View File
@@ -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:
-3
View File
@@ -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 = "");
-4
View File
@@ -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)
+9 -9
View File
@@ -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
View File
@@ -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) {
-38
View File
@@ -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
-32
View File
@@ -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/
+4 -21
View File
@@ -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):
+1
View File
@@ -18,6 +18,7 @@
#include "LIEF/utils.hpp"
#include "LIEF/ART/EnumToString.hpp"
#include "LIEF/PE/utils.hpp"
namespace LIEF {
namespace ART {
-126
View File
@@ -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;
}
-2
View File
@@ -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"
-27
View File
@@ -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_;
}
-128
View File
@@ -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;
}
}
-8
View File
@@ -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_;
-22
View File
@@ -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
View File
@@ -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
-7
View File
@@ -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());
-24
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
-39
View File
@@ -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
View File
@@ -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>();
}
}
}
-27
View File
@@ -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_;
}
+1 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
});
+9 -21
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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