4
0
mirror of https://github.com/QuasarApp/LIEF.git synced 2025-05-11 03:09:32 +00:00

Add object (ELF::DynamicEntryFlags) for ELF's DT_FLAGS and DT_FLAGS_1

This commit is contained in:
Romain Thomas 2017-08-01 15:22:01 +02:00
parent c82b1fb658
commit 754b8afa2b
28 changed files with 633 additions and 44 deletions

@ -11,6 +11,7 @@ set(LIEF_PYTHON_ELF_SRC
"${CMAKE_CURRENT_LIST_DIR}/objects/pyHeader.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pySymbolVersionAux.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDynamicEntryArray.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDynamicEntryFlags.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pySegment.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pySection.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDynamicEntryRpath.cpp"

@ -0,0 +1,93 @@
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pyELF.hpp"
#include "LIEF/visitors/Hash.hpp"
#include "LIEF/ELF/DynamicEntryFlags.hpp"
#include "LIEF/ELF/DynamicEntry.hpp"
#include <string>
#include <sstream>
template<class T>
using getter_t = T (DynamicEntryFlags::*)(void) const;
template<class T>
using setter_t = void (DynamicEntryFlags::*)(T);
void init_ELF_DynamicEntryFlags_class(py::module& m) {
py::class_<DynamicEntryFlags, DynamicEntry>(m, "DynamicEntryFlags")
.def(py::init<>())
.def_property_readonly("flags",
&DynamicEntryFlags::flags,
"Return list of " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS) " or " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS_1) " (integer)",
py::return_value_policy::move)
.def("add",
static_cast<void (DynamicEntryFlags::*)(DYNAMIC_FLAGS)>(&DynamicEntryFlags::add),
"Add the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS) "",
"flag"_a)
.def("add",
static_cast<void (DynamicEntryFlags::*)(DYNAMIC_FLAGS_1)>(&DynamicEntryFlags::add),
"Add the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS_1) "",
"flag"_a)
.def("remove",
static_cast<void (DynamicEntryFlags::*)(DYNAMIC_FLAGS)>(&DynamicEntryFlags::remove),
"Remove the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS) "",
"flag"_a)
.def("remove",
static_cast<void (DynamicEntryFlags::*)(DYNAMIC_FLAGS_1)>(&DynamicEntryFlags::remove),
"Remove the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS_1) "",
"flag"_a)
.def("__eq__", &DynamicEntryFlags::operator==)
.def("__ne__", &DynamicEntryFlags::operator!=)
.def("__hash__",
[] (const DynamicEntryFlags& entry) {
return LIEF::Hash::hash(entry);
})
.def(py::self += DYNAMIC_FLAGS())
.def(py::self += DYNAMIC_FLAGS_1())
.def(py::self -= DYNAMIC_FLAGS())
.def(py::self -= DYNAMIC_FLAGS_1())
.def("__contains__",
static_cast<bool (DynamicEntryFlags::*)(DYNAMIC_FLAGS) const>(&DynamicEntryFlags::has),
"Check if the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS) " is present")
.def("__contains__",
static_cast<bool (DynamicEntryFlags::*)(DYNAMIC_FLAGS_1) const>(&DynamicEntryFlags::has),
"Check if the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS_1) " is present")
.def("__str__",
[] (const DynamicEntryFlags& entry)
{
std::ostringstream stream;
stream << entry;
std::string str = stream.str();
return str;
});
}

@ -43,6 +43,7 @@ void init_ELF_module(py::module& m) {
init_ELF_DynamicEntryArray_class(LIEF_ELF_module);
init_ELF_DynamicEntryRpath_class(LIEF_ELF_module);
init_ELF_DynamicEntryRunPath_class(LIEF_ELF_module);
init_ELF_DynamicEntryFlags_class(LIEF_ELF_module);
init_ELF_GnuHash_class(LIEF_ELF_module);
init_ELF_SysvHash_class(LIEF_ELF_module);
init_ELF_Builder_class(LIEF_ELF_module);

@ -41,6 +41,7 @@ void init_ELF_DynamicSharedObject_class(py::module&);
void init_ELF_DynamicEntryArray_class(py::module&);
void init_ELF_DynamicEntryRpath_class(py::module&);
void init_ELF_DynamicEntryRunPath_class(py::module&);
void init_ELF_DynamicEntryFlags_class(py::module&);
void init_ELF_GnuHash_class(py::module&);
void init_ELF_SysvHash_class(py::module&);
void init_ELF_Builder_class(py::module&);

@ -433,7 +433,7 @@ void init_ELF_Structures_enum(py::module& m) {
.value(PY_ENUM(DYNAMIC_TAGS::DT_FINI_ARRAYSZ))
.value(PY_ENUM(DYNAMIC_TAGS::DT_RUNPATH))
.value(PY_ENUM(DYNAMIC_TAGS::DT_FLAGS))
.value(PY_ENUM(DYNAMIC_TAGS::DT_ENCODING))
//.value(PY_ENUM(DYNAMIC_TAGS::DT_ENCODING))
.value(PY_ENUM(DYNAMIC_TAGS::DT_PREINIT_ARRAY))
.value(PY_ENUM(DYNAMIC_TAGS::DT_PREINIT_ARRAYSZ))
.value(PY_ENUM(DYNAMIC_TAGS::DT_LOOS))
@ -1027,4 +1027,33 @@ void init_ELF_Structures_enum(py::module& m) {
.value(PY_ENUM(DYNAMIC_FLAGS::DF_STATIC_TLS))
.export_values();
py::enum_<DYNAMIC_FLAGS_1>(m, "DYNAMIC_FLAGS_1")
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_NOW))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_GLOBAL))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_GROUP))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_NODELETE))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_LOADFLTR))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_INITFIRST))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_NOOPEN))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_ORIGIN))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_DIRECT))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_TRANS))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_INTERPOSE))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_NODEFLIB))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_NODUMP))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_CONFALT))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_ENDFILTEE))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_DISPRELDNE))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_DISPRELPND))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_NODIRECT))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_IGNMULDEF))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_NOKSYMS))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_NOHDR))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_EDITED))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_NORELOC))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_SYMINTPOSE))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_GLOBAUDIT))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_SINGLETON))
.export_values();
}

@ -33,6 +33,7 @@ void init_json_functions(py::module& m) {
m.def("to_json", &LIEF::to_json_str<LIEF::ELF::DynamicEntryRpath, LIEF::ELF::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::ELF::DynamicEntryRunPath, LIEF::ELF::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::ELF::DynamicSharedObject, LIEF::ELF::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::ELF::DynamicEntryFlags, LIEF::ELF::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::ELF::Symbol, LIEF::ELF::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::ELF::Relocation, LIEF::ELF::JsonVisitor>);
m.def("to_json", &LIEF::to_json_str<LIEF::ELF::SymbolVersion, LIEF::ELF::JsonVisitor>);

@ -18,6 +18,7 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/operators.h>
#include <functional>
#include "encoding.hpp"

@ -94,6 +94,14 @@ Elf_DynamicEntry_RunPath_t
.. doxygenstruct:: Elf_DynamicEntry_RunPath_t
:project: lief
----------
Elf_DynamicEntry_Flags_t
~~~~~~~~~~~~~~~~~~~~~~~~~~
.. doxygenstruct:: Elf_DynamicEntry_Flags_t
:project: lief
Utilities
*********

@ -92,6 +92,14 @@ Dynamic Entry Array
----------
Dynamic Entry Flags
*******************
.. doxygenclass:: LIEF::ELF::DynamicEntryFlags
:project: lief
----------
Relocations
***********
@ -293,6 +301,13 @@ Dynamic flags
----------
Dynamic flags 1
~~~~~~~~~~~~~~~
.. doxygenenum:: LIEF::ELF::DYNAMIC_FLAGS_1
:project: lief
----------
Dynamic symbols counting
~~~~~~~~~~~~~~~~~~~~~~~~

@ -110,6 +110,17 @@ Dynamic Entry Array
----------
Dynamic Entry Flags
*******************
.. autoclass:: lief.ELF.DynamicEntryFlags
:members:
:inherited-members:
:undoc-members:
----------
Relocations
***********
@ -351,6 +362,17 @@ Dynamic flags
----------
Dynamic flags 1
~~~~~~~~~~~~~~~
.. autoclass:: lief.ELF.DYNAMIC_FLAGS_1
:members:
:inherited-members:
:undoc-members:
----------
Symbol types
~~~~~~~~~~~~

@ -152,24 +152,33 @@ def print_segments(binary):
@exceptions_handler(Exception)
def print_dynamic_entries(binary):
dynamicEntries = binary.dynamic_entries
dynamic_entries = binary.dynamic_entries
# Dynamic entries
if len(dynamicEntries) > 0:
print("== Dynamic entries ==\n")
f_title = "|{:<12} | {:<10}| {:<20}|"
f_value = "|{:<12} | 0x{:<8x}| {:<20}|"
print(f_title.format("Tag", "Value", "Info"))
for dynEntry in dynamicEntries:
if dynEntry.tag == ELF.DYNAMIC_TAGS.NULL:
continue
if dynEntry.tag in [ELF.DYNAMIC_TAGS.SONAME, ELF.DYNAMIC_TAGS.NEEDED, ELF.DYNAMIC_TAGS.RUNPATH, ELF.DYNAMIC_TAGS.RPATH]:
print(f_value.format(str(dynEntry.tag).split(".")[-1], dynEntry.value, dynEntry.name))
elif dynEntry.tag in [ELF.DYNAMIC_TAGS.INIT_ARRAY,ELF.DYNAMIC_TAGS.FINI_ARRAY]:
print(f_value.format(str(dynEntry.tag).split(".")[-1], dynEntry.value, ", ".join(map(hex, dynEntry.array))))
else:
print(f_value.format(str(dynEntry.tag).split(".")[-1], dynEntry.value, ""))
if len(dynamic_entries) == 0:
return
print("")
print("== Dynamic entries ==\n")
f_title = "|{:<16} | {:<10}| {:<20}|"
f_value = "|{:<16} | 0x{:<8x}| {:<20}|"
print(f_title.format("Tag", "Value", "Info"))
for entry in dynamic_entries:
if entry.tag == ELF.DYNAMIC_TAGS.NULL:
continue
if entry.tag in [ELF.DYNAMIC_TAGS.SONAME, ELF.DYNAMIC_TAGS.NEEDED, ELF.DYNAMIC_TAGS.RUNPATH, ELF.DYNAMIC_TAGS.RPATH]:
print(f_value.format(str(entry.tag).split(".")[-1], entry.value, entry.name))
elif type(entry) is ELF.DynamicEntryArray: # [ELF.DYNAMIC_TAGS.INIT_ARRAY,ELF.DYNAMIC_TAGS.FINI_ARRAY]:
print(f_value.format(str(entry.tag).split(".")[-1], entry.value, ", ".join(map(hex, entry.array))))
elif entry.tag == ELF.DYNAMIC_TAGS.FLAGS:
flags_str = " - ".join([str(ELF.DYNAMIC_FLAGS(s)).split(".")[-1] for s in entry.flags])
print(f_value.format(str(entry.tag).split(".")[-1], entry.value, flags_str))
elif entry.tag == ELF.DYNAMIC_TAGS.FLAGS_1:
flags_str = " - ".join([str(ELF.DYNAMIC_FLAGS_1(s)).split(".")[-1] for s in entry.flags])
print(f_value.format(str(entry.tag).split(".")[-1], entry.value, flags_str))
else:
print(f_value.format(str(entry.tag).split(".")[-1], entry.value, ""))
print("")
@exceptions_handler(Exception)

@ -35,6 +35,7 @@
#include "LIEF/ELF/DynamicEntryRpath.hpp"
#include "LIEF/ELF/DynamicEntryRunPath.hpp"
#include "LIEF/ELF/DynamicEntryArray.hpp"
#include "LIEF/ELF/DynamicEntryFlags.hpp"
#include "LIEF/ELF/Symbol.hpp"
#include "LIEF/ELF/Relocation.hpp"
#include "LIEF/ELF/SymbolVersion.hpp"

@ -0,0 +1,72 @@
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_ELF_DYNAMIC_ENTRY_FLAGS_H_
#define LIEF_ELF_DYNAMIC_ENTRY_FLAGS_H_
#include <string>
#include "LIEF/visibility.h"
#include "LIEF/ELF/type_traits.hpp"
#include "LIEF/ELF/DynamicEntry.hpp"
namespace LIEF {
namespace ELF {
class DLL_PUBLIC DynamicEntryFlags : public DynamicEntry {
public:
using DynamicEntry::DynamicEntry;
DynamicEntryFlags(void);
DynamicEntryFlags& operator=(const DynamicEntryFlags&);
DynamicEntryFlags(const DynamicEntryFlags&);
//! @brief If the current entry has the given DYNAMIC_FLAGS
bool has(DYNAMIC_FLAGS f) const;
//! @brief If the current entry has the given DYNAMIC_FLAGS_1
bool has(DYNAMIC_FLAGS_1 f) const;
//! @brief Return flags as a list of integers
dynamic_flags_list_t flags(void) const;
//! @brief Add the given DYNAMIC_FLAGS
void add(DYNAMIC_FLAGS f);
//! @brief Add the given DYNAMIC_FLAGS_1
void add(DYNAMIC_FLAGS_1 f);
//! @brief Remove the given DYNAMIC_FLAGS
void remove(DYNAMIC_FLAGS f);
//! @brief Remove the given DYNAMIC_FLAGS_1
void remove(DYNAMIC_FLAGS_1 f);
DynamicEntryFlags& operator+=(DYNAMIC_FLAGS f);
DynamicEntryFlags& operator+=(DYNAMIC_FLAGS_1 f);
DynamicEntryFlags& operator-=(DYNAMIC_FLAGS f);
DynamicEntryFlags& operator-=(DYNAMIC_FLAGS_1 f);
//! @brief Method so that the ``visitor`` can visit us
virtual void accept(Visitor& visitor) const override;
virtual std::ostream& print(std::ostream& os) const override;
};
}
}
#endif

@ -44,6 +44,7 @@ DLL_PUBLIC const char* to_string(RELOCATION_PURPOSES e);
DLL_PUBLIC const char* to_string(IDENTITY e);
DLL_PUBLIC const char* to_string(SYMBOL_SECTION_INDEX e);
DLL_PUBLIC const char* to_string(DYNAMIC_FLAGS e);
DLL_PUBLIC const char* to_string(DYNAMIC_FLAGS_1 e);
DLL_PUBLIC const char* to_string(PPC64_EFLAGS e);
DLL_PUBLIC const char* to_string(ARM_EFLAGS e);

@ -98,6 +98,45 @@ static const HEXAGON_EFLAGS hexagon_eflags_array[] = {
HEXAGON_EFLAGS::EF_HEXAGON_ISA_V5,
};
static const DYNAMIC_FLAGS dynamic_flags_array[] = {
DYNAMIC_FLAGS::DF_ORIGIN,
DYNAMIC_FLAGS::DF_SYMBOLIC,
DYNAMIC_FLAGS::DF_TEXTREL,
DYNAMIC_FLAGS::DF_BIND_NOW,
DYNAMIC_FLAGS::DF_STATIC_TLS,
};
static const DYNAMIC_FLAGS_1 dynamic_flags_1_array[] = {
DYNAMIC_FLAGS_1::DF_1_NOW,
DYNAMIC_FLAGS_1::DF_1_GLOBAL,
DYNAMIC_FLAGS_1::DF_1_GROUP,
DYNAMIC_FLAGS_1::DF_1_NODELETE,
DYNAMIC_FLAGS_1::DF_1_LOADFLTR,
DYNAMIC_FLAGS_1::DF_1_INITFIRST,
DYNAMIC_FLAGS_1::DF_1_NOOPEN,
DYNAMIC_FLAGS_1::DF_1_ORIGIN,
DYNAMIC_FLAGS_1::DF_1_DIRECT,
DYNAMIC_FLAGS_1::DF_1_TRANS,
DYNAMIC_FLAGS_1::DF_1_INTERPOSE,
DYNAMIC_FLAGS_1::DF_1_NODEFLIB,
DYNAMIC_FLAGS_1::DF_1_NODUMP,
DYNAMIC_FLAGS_1::DF_1_CONFALT,
DYNAMIC_FLAGS_1::DF_1_ENDFILTEE,
DYNAMIC_FLAGS_1::DF_1_DISPRELDNE,
DYNAMIC_FLAGS_1::DF_1_DISPRELPND,
DYNAMIC_FLAGS_1::DF_1_NODIRECT,
DYNAMIC_FLAGS_1::DF_1_IGNMULDEF,
DYNAMIC_FLAGS_1::DF_1_NOKSYMS,
DYNAMIC_FLAGS_1::DF_1_NOHDR,
DYNAMIC_FLAGS_1::DF_1_EDITED,
DYNAMIC_FLAGS_1::DF_1_NORELOC,
DYNAMIC_FLAGS_1::DF_1_SYMINTPOSE,
DYNAMIC_FLAGS_1::DF_1_GLOBAUDIT,
DYNAMIC_FLAGS_1::DF_1_SINGLETON,
};
class ELF32 {
public:

@ -803,16 +803,15 @@ enum DYNAMIC_TAGS {
DT_MIPS_RWPLT = 0x70000034 /**< Points to the base of a writable PLT. */
};
/** DT_FLAGS values. */
/** DT_FLAGS and DT_FLAGS_1 values. */
enum DYNAMIC_FLAGS {
DF_ORIGIN = 0x01, /**< The object may reference $ORIGIN. */
DF_SYMBOLIC = 0x02, /**< Search the shared lib before searching the exe. */
DF_TEXTREL = 0x04, /**< Relocations may modify a non-writable segment. */
DF_BIND_NOW = 0x08, /**< Process all relocations on load. */
DF_STATIC_TLS = 0x10 /**< Reject attempts to load dynamically. */
DF_ORIGIN = 0x00000001, /**< The object may reference $ORIGIN. */
DF_SYMBOLIC = 0x00000002, /**< Search the shared lib before searching the exe. */
DF_TEXTREL = 0x00000004, /**< Relocations may modify a non-writable segment. */
DF_BIND_NOW = 0x00000008, /**< Process all relocations on load. */
DF_STATIC_TLS = 0x00000010, /**< Reject attempts to load dynamically. */
};
/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 entry. */
enum DYNAMIC_FLAGS_1 {
DF_1_NOW = 0x00000001, /**< Set RTLD_NOW for this object. */
DF_1_GLOBAL = 0x00000002, /**< Set RTLD_GLOBAL for this object. */

@ -16,6 +16,7 @@
#ifndef LIEF_ELF_TYPE_TRAITS_H_
#define LIEF_ELF_TYPE_TRAITS_H_
#include <vector>
#include <set>
#include "LIEF/iterators.hpp"
#include "LIEF/ELF/Structures.hpp"
@ -102,6 +103,8 @@ using arm_flags_list_t = flags_list_t<ARM_EFLAGS>;
using mips_flags_list_t = flags_list_t<MIPS_EFLAGS>;
using hexagon_flags_list_t = flags_list_t<HEXAGON_EFLAGS>;
using ppc64_flags_list_t = flags_list_t<PPC64_EFLAGS>;
using dynamic_flags_list_t = flags_list_t<uint32_t>;
}
}

@ -54,6 +54,7 @@ class DynamicEntryLibrary;
class DynamicSharedObject;
class DynamicEntryRunPath;
class DynamicEntryRpath;
class DynamicEntryFlags;
class Symbol;
class SymbolVersion;
@ -229,6 +230,9 @@ class DLL_PUBLIC Visitor {
//! @brief Method to visit a LIEF::ELF::DynamicEntryRpath
virtual void visit(const ELF::DynamicEntryRpath& rpath);
//! @brief Method to visit a LIEF::ELF::DynamicEntryFlags
virtual void visit(const ELF::DynamicEntryFlags& flags);
//! @brief Method to visit a LIEF::ELF::Symbol
virtual void visit(const ELF::Symbol& symbol);

@ -38,6 +38,7 @@ class DLL_PUBLIC JsonVisitor : public LIEF::JsonVisitor {
virtual void visit(const DynamicEntryRpath& entry) override;
virtual void visit(const DynamicEntryRunPath& entry) override;
virtual void visit(const DynamicSharedObject& entry) override;
virtual void visit(const DynamicEntryFlags& entry) override;
virtual void visit(const Symbol& symbol) override;
virtual void visit(const Relocation& relocation) override;
virtual void visit(const SymbolVersion& sv) override;

@ -40,6 +40,7 @@ set(LIEF_ELF_SRC
"${CMAKE_CURRENT_LIST_DIR}/SymbolVersionDefinition.cpp"
"${CMAKE_CURRENT_LIST_DIR}/DynamicEntry.cpp"
"${CMAKE_CURRENT_LIST_DIR}/DynamicEntryRpath.cpp"
"${CMAKE_CURRENT_LIST_DIR}/DynamicEntryFlags.cpp"
"${CMAKE_CURRENT_LIST_DIR}/Builder.tcc"
"${CMAKE_CURRENT_LIST_DIR}/Parser.tcc")
@ -49,6 +50,7 @@ set(LIEF_ELF_INC_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/ELF/Builder.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/ELF/DynamicEntry.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/ELF/DynamicEntryArray.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/ELF/DynamicEntryFlags.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/ELF/DynamicEntryLibrary.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/ELF/DynamicEntryRpath.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/ELF/DynamicEntryRunPath.hpp"

@ -67,7 +67,7 @@ std::ostream& DynamicEntryArray::print(std::ostream& os) const {
[] (std::string& s, uint64_t x) {
std::stringstream ss;
ss << "0x" << std::hex << x;
return s.empty() ? ss.str() : " ," + ss.str();
return s.empty() ? ss.str() : s + ", " + ss.str();
})
<< "]";

@ -0,0 +1,165 @@
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <numeric>
#include <sstream>
#include <iomanip>
#include "LIEF/ELF/DynamicEntryFlags.hpp"
#include "LIEF/ELF/EnumToString.hpp"
namespace LIEF {
namespace ELF {
DynamicEntryFlags::DynamicEntryFlags(void) = default;
DynamicEntryFlags& DynamicEntryFlags::operator=(const DynamicEntryFlags&) = default;
DynamicEntryFlags::DynamicEntryFlags(const DynamicEntryFlags&) = default;
bool DynamicEntryFlags::has(DYNAMIC_FLAGS f) const {
if (this->tag() != DYNAMIC_TAGS::DT_FLAGS) {
return false;
}
return (f & this->value()) > 0;
}
bool DynamicEntryFlags::has(DYNAMIC_FLAGS_1 f) const {
if (this->tag() != DYNAMIC_TAGS::DT_FLAGS_1) {
return false;
}
return (f & this->value()) > 0;
}
dynamic_flags_list_t DynamicEntryFlags::flags(void) const {
dynamic_flags_list_t flags;
std::copy_if(
std::begin(dynamic_flags_array),
std::end(dynamic_flags_array),
std::inserter(flags, std::begin(flags)),
std::bind(static_cast<bool (DynamicEntryFlags::*)(DYNAMIC_FLAGS) const>(&DynamicEntryFlags::has),
this, std::placeholders::_1));
std::copy_if(
std::begin(dynamic_flags_1_array),
std::end(dynamic_flags_1_array),
std::inserter(flags, std::begin(flags)),
std::bind(static_cast<bool (DynamicEntryFlags::*)(DYNAMIC_FLAGS_1) const>(&DynamicEntryFlags::has),
this, std::placeholders::_1));
return flags;
}
void DynamicEntryFlags::add(DYNAMIC_FLAGS f) {
if (this->tag() != DYNAMIC_TAGS::DT_FLAGS) {
return;
}
this->value(this->value() | static_cast<uint64_t>(f));
}
void DynamicEntryFlags::add(DYNAMIC_FLAGS_1 f) {
if (this->tag() != DYNAMIC_TAGS::DT_FLAGS_1) {
return;
}
this->value(this->value() | static_cast<uint64_t>(f));
}
void DynamicEntryFlags::remove(DYNAMIC_FLAGS f) {
if (this->tag() != DYNAMIC_TAGS::DT_FLAGS) {
return;
}
this->value(this->value() & (~ static_cast<uint64_t>(f)));
}
void DynamicEntryFlags::remove(DYNAMIC_FLAGS_1 f) {
if (this->tag() != DYNAMIC_TAGS::DT_FLAGS_1) {
return;
}
this->value(this->value() & (~ static_cast<uint64_t>(f)));
}
DynamicEntryFlags& DynamicEntryFlags::operator+=(DYNAMIC_FLAGS f) {
this->add(f);
return *this;
}
DynamicEntryFlags& DynamicEntryFlags::operator+=(DYNAMIC_FLAGS_1 f) {
this->add(f);
return *this;
}
DynamicEntryFlags& DynamicEntryFlags::operator-=(DYNAMIC_FLAGS f) {
this->remove(f);
return *this;
}
DynamicEntryFlags& DynamicEntryFlags::operator-=(DYNAMIC_FLAGS_1 f) {
this->remove(f);
return *this;
}
void DynamicEntryFlags::accept(Visitor& visitor) const {
DynamicEntry::accept(visitor);
visitor(*this); // Double dispatch to avoid down-casting
for (uint32_t f : this->flags()) {
visitor.visit(f);
}
}
std::ostream& DynamicEntryFlags::print(std::ostream& os) const {
DynamicEntry::print(os);
const dynamic_flags_list_t& flags = this->flags();
std::string flags_str = "";
if (this->tag() == DYNAMIC_TAGS::DT_FLAGS) {
flags_str = std::accumulate(
std::begin(flags),
std::end(flags), std::string{},
[] (const std::string& a, uint32_t b) {
DYNAMIC_FLAGS flag = static_cast<DYNAMIC_FLAGS>(b);
return a.empty() ? to_string(flag) : a + " - " + to_string(flag);
});
}
if (this->tag() == DYNAMIC_TAGS::DT_FLAGS_1) {
flags_str = std::accumulate(
std::begin(flags),
std::end(flags), std::string{},
[] (const std::string& a, uint32_t b) {
DYNAMIC_FLAGS_1 flag = static_cast<DYNAMIC_FLAGS_1>(b);
return a.empty() ? to_string(flag) : a + " - " + to_string(flag);
});
}
os << " " << flags_str;
return os;
}
}
}

@ -306,7 +306,7 @@ const char* to_string(DYNAMIC_TAGS e) {
{ DYNAMIC_TAGS::DT_FINI_ARRAYSZ, "FINI_ARRAYSZ"},
{ DYNAMIC_TAGS::DT_RUNPATH, "RUNPATH"},
{ DYNAMIC_TAGS::DT_FLAGS, "FLAGS"},
{ DYNAMIC_TAGS::DT_ENCODING, "ENCODING"},
//{ DYNAMIC_TAGS::DT_ENCODING, "ENCODING"}, // SKIPED
{ DYNAMIC_TAGS::DT_PREINIT_ARRAY, "PREINIT_ARRAY"},
{ DYNAMIC_TAGS::DT_PREINIT_ARRAYSZ, "PREINIT_ARRAYSZ"},
{ DYNAMIC_TAGS::DT_LOOS, "LOOS"},
@ -1087,16 +1087,50 @@ const char* to_string(SYMBOL_SECTION_INDEX e) {
const char* to_string(DYNAMIC_FLAGS e) {
const std::map<DYNAMIC_FLAGS, const char*> enumStrings {
{ DYNAMIC_FLAGS::DF_ORIGIN, "ORIGIN" },
{ DYNAMIC_FLAGS::DF_SYMBOLIC, "SYMBOLIC" },
{ DYNAMIC_FLAGS::DF_TEXTREL, "TEXTREL" },
{ DYNAMIC_FLAGS::DF_BIND_NOW, "BIND_NOW" },
{ DYNAMIC_FLAGS::DF_STATIC_TLS, "STATIC_TLS" },
const std::map<DYNAMIC_FLAGS, const char*> enum_strings {
{ DYNAMIC_FLAGS::DF_ORIGIN, "ORIGIN" },
{ DYNAMIC_FLAGS::DF_SYMBOLIC, "SYMBOLIC" },
{ DYNAMIC_FLAGS::DF_TEXTREL, "TEXTREL" },
{ DYNAMIC_FLAGS::DF_BIND_NOW, "BIND_NOW" },
{ DYNAMIC_FLAGS::DF_STATIC_TLS, "STATIC_TLS" },
};
auto it = enumStrings.find(e);
return it == enumStrings.end() ? "UNDEFINED" : it->second;
auto it = enum_strings.find(e);
return it == enum_strings.end() ? "UNDEFINED" : it->second;
}
const char* to_string(DYNAMIC_FLAGS_1 e) {
const std::map<DYNAMIC_FLAGS_1, const char*> enum_strings_flags1 {
{ DYNAMIC_FLAGS_1::DF_1_NOW, "NOW" },
{ DYNAMIC_FLAGS_1::DF_1_GLOBAL, "GLOBAL" },
{ DYNAMIC_FLAGS_1::DF_1_GROUP, "GROUP" },
{ DYNAMIC_FLAGS_1::DF_1_NODELETE, "NODELETE" },
{ DYNAMIC_FLAGS_1::DF_1_LOADFLTR, "LOADFLTR" },
{ DYNAMIC_FLAGS_1::DF_1_INITFIRST, "INITFIRST" },
{ DYNAMIC_FLAGS_1::DF_1_NOOPEN, "NOOPEN" },
{ DYNAMIC_FLAGS_1::DF_1_ORIGIN, "ORIGIN" },
{ DYNAMIC_FLAGS_1::DF_1_DIRECT, "DIRECT" },
{ DYNAMIC_FLAGS_1::DF_1_TRANS, "TRANS" },
{ DYNAMIC_FLAGS_1::DF_1_INTERPOSE, "INTERPOSE" },
{ DYNAMIC_FLAGS_1::DF_1_NODEFLIB, "NODEFLIB" },
{ DYNAMIC_FLAGS_1::DF_1_NODUMP, "NODUMP" },
{ DYNAMIC_FLAGS_1::DF_1_CONFALT, "CONFALT" },
{ DYNAMIC_FLAGS_1::DF_1_ENDFILTEE, "ENDFILTEE" },
{ DYNAMIC_FLAGS_1::DF_1_DISPRELDNE, "DISPRELDNE" },
{ DYNAMIC_FLAGS_1::DF_1_DISPRELPND, "DISPRELPND" },
{ DYNAMIC_FLAGS_1::DF_1_NODIRECT, "NODIRECT" },
{ DYNAMIC_FLAGS_1::DF_1_IGNMULDEF, "IGNMULDEF" },
{ DYNAMIC_FLAGS_1::DF_1_NOKSYMS, "NOKSYMS" },
{ DYNAMIC_FLAGS_1::DF_1_NOHDR, "NOHDR" },
{ DYNAMIC_FLAGS_1::DF_1_EDITED, "EDITED" },
{ DYNAMIC_FLAGS_1::DF_1_NORELOC, "NORELOC" },
{ DYNAMIC_FLAGS_1::DF_1_SYMINTPOSE, "SYMINTPOSE" },
{ DYNAMIC_FLAGS_1::DF_1_GLOBAUDIT, "GLOBAUDIT" },
{ DYNAMIC_FLAGS_1::DF_1_SINGLETON, "SINGLETON" },
};
auto it = enum_strings_flags1.find(e);
return it == enum_strings_flags1.end() ? "UNDEFINED" : it->second;
}

@ -17,6 +17,7 @@
#include <map>
#include <iomanip>
#include <sstream>
#include <numeric>
#include "LIEF/exception.hpp"
#include "LIEF/visitors/Hash.hpp"
@ -567,6 +568,52 @@ std::ostream& operator<<(std::ostream& os, const Header& hdr)
ss << static_cast<uint32_t>(identity[IDENTITY::EI_MAG3]) << " ";
const std::string& ident_magic = ss.str();
std::string processor_flags_str = "";
if (hdr.machine_type() == ARCH::EM_ARM) {
const arm_flags_list_t& flags = hdr.arm_flags_list();
processor_flags_str = std::accumulate(
std::begin(flags),
std::end(flags), std::string{},
[] (const std::string& a, ARM_EFLAGS b) {
return a.empty() ? to_string(b) : a + " " + to_string(b);
});
}
if (hdr.machine_type() == ARCH::EM_PPC64) {
const ppc64_flags_list_t& flags = hdr.ppc64_flags_list();
processor_flags_str = std::accumulate(
std::begin(flags),
std::end(flags), std::string{},
[] (const std::string& a, PPC64_EFLAGS b) {
return a.empty() ? to_string(b) : a + " " + to_string(b);
});
}
if (hdr.machine_type() == ARCH::EM_HEXAGON) {
const hexagon_flags_list_t& flags = hdr.hexagon_flags_list();
processor_flags_str = std::accumulate(
std::begin(flags),
std::end(flags), std::string{},
[] (const std::string& a, HEXAGON_EFLAGS b) {
return a.empty() ? to_string(b) : a + " " + to_string(b);
});
}
if (hdr.machine_type() == ARCH::EM_MIPS or
hdr.machine_type() == ARCH::EM_MIPS_RS3_LE or
hdr.machine_type() == ARCH::EM_MIPS_X) {
const mips_flags_list_t& flags = hdr.mips_flags_list();
processor_flags_str = std::accumulate(
std::begin(flags),
std::end(flags), std::string{},
[] (const std::string& a, MIPS_EFLAGS b) {
return a.empty() ? to_string(b) : a + " " + to_string(b);
});
}
os << std::hex << std::left;
os << std::setw(33) << std::setfill(' ') << "Magic:" << ident_magic << std::endl;
os << std::setw(33) << std::setfill(' ') << "Class" << to_string(hdr.identity_class()) << std::endl;
@ -579,7 +626,7 @@ std::ostream& operator<<(std::ostream& os, const Header& hdr)
os << std::setw(33) << std::setfill(' ') << "Entry Point:" << "0x" << hdr.entrypoint() << std::endl;
os << std::setw(33) << std::setfill(' ') << "Program header offset:" << "0x" << hdr.program_headers_offset() << std::endl;
os << std::setw(33) << std::setfill(' ') << "Section header offset:" << hdr.section_headers_offset() << std::endl;
os << std::setw(33) << std::setfill(' ') << "Processor Flag" << hdr.processor_flag() << std::endl;
os << std::setw(33) << std::setfill(' ') << "Processor Flag" << hdr.processor_flag() << " " << processor_flags_str << std::endl;
os << std::setw(33) << std::setfill(' ') << "Header size:" << hdr.header_size() << std::endl;
os << std::setw(33) << std::setfill(' ') << "Size of program header :" << hdr.program_header_size() << std::endl;
os << std::setw(33) << std::setfill(' ') << "Number of program header:" << hdr.numberof_segments() << std::endl;

@ -14,8 +14,11 @@
* limitations under the License.
*/
#include "easylogging++.h"
#include "LIEF/utils.hpp"
#include "LIEF/ELF/DynamicEntryFlags.hpp"
namespace LIEF {
namespace ELF {
template<typename ELF_T>
@ -1019,8 +1022,14 @@ void Parser::parse_dynamic_entries(uint64_t offset, uint64_t size) {
break;
}
case DYNAMIC_TAGS::DT_FLAGS_1:
case DYNAMIC_TAGS::DT_FLAGS:
{
dynamic_entry = new DynamicEntryFlags{entry};
break;
}
case DYNAMIC_TAGS::DT_SYMTAB :
case DYNAMIC_TAGS::DT_SYMTAB:
{
dynamic_entry = new DynamicEntry{entry};
break;

@ -108,6 +108,10 @@ void Visitor::visit(const ELF::DynamicEntryRpath& rpath) {
rpath.accept(*this);
}
void Visitor::visit(const ELF::DynamicEntryFlags& flags) {
flags.accept(*this);
}
void Visitor::visit(const ELF::Symbol& symbol) {
symbol.accept(*this);
}

@ -249,6 +249,34 @@ void JsonVisitor::visit(const DynamicSharedObject& entry) {
this->node_["library"] = entry.name();
}
void JsonVisitor::visit(const DynamicEntryFlags& entry) {
const dynamic_flags_list_t& flags = entry.flags();
std::vector<std::string> flags_str;
flags_str.reserve(flags.size());
if (entry.tag() == DYNAMIC_TAGS::DT_FLAGS) {
std::transform(
std::begin(flags), std::end(flags),
std::back_inserter(flags_str),
[] (uint32_t f) {
return to_string(static_cast<DYNAMIC_FLAGS>(f));
});
}
if (entry.tag() == DYNAMIC_TAGS::DT_FLAGS_1) {
std::transform(
std::begin(flags), std::end(flags),
std::back_inserter(flags_str),
[] (uint32_t f) {
return to_string(static_cast<DYNAMIC_FLAGS_1>(f));
});
}
this->node_["flags"] = flags_str;
}
void JsonVisitor::visit(const Symbol& symbol) {
this->node_["type"] = to_string(symbol.type());
this->node_["binding"] = to_string(symbol.binding());

@ -204,15 +204,14 @@ class TestELF(TestCase):
dynsym = list(rvs.dynamic_symbols)
self.assertEqual(len(dynsym), 10)
def test_dynamic_flags(self):
sample = "ELF/ELF32_ARM_binary_ls.bin"
ls = lief.parse(get_sample(sample))
d_flags = ls.dynamic_entry_from_tag(lief.ELF.DYNAMIC_TAGS.FLAGS)
d_flags_1 = ls.dynamic_entry_from_tag(lief.ELF.DYNAMIC_TAGS.FLAGS_1)
self.assertIn(lief.ELF.DYNAMIC_FLAGS.BIND_NOW, d_flags)
self.assertIn(lief.ELF.DYNAMIC_FLAGS_1.NOW, d_flags_1)
if __name__ == '__main__':